Tivoli Service Desk 6.0 Developer's Toolkit Script プログラミングの手引き

第 8 章: データベース管理機能

目次に戻る


概要

Developer's Toolkit は、クライアント / サーバー・データベース・アプリケーションのビルド処理を単純化するために特別に設計されました。そのために、TSD Script 言語には、SQL データベースとの対話専用の 1 セットのステートメントが含まれています。

TSD Script SQL インターフェースは、その言語に組み込まれている 1 つの部分です。SQL インターフェースは TSD Script RECORD および LIST タイプに柔軟性を持たせるのに効力を発揮します。さらに、TSD Script SQL ステートメントは、信頼性のある複数ユーザー・アプリケーションの開発のために組み込まれた受動並行性を提供します。

特に有用なもう 1 つの機能は、Oracle による配列取り出しが使用できることです。配列取り出しは、データベースの照会に必要な時間を大幅に短縮できます。

SQL の概説

SQL または 構造化照会言語は、次を行なうために使用する業界標準言語です。

本書は SQL の学習が目的ではないので、この章を読む前に SQL 構文を理解していると便利です。

サポートされるデータベース

Developer's Toolkit でサポートされるデータベース (ソースとも呼ばれる) は次の通りです。

Developer's Toolkit での SQL サポート

Developer's Toolkit および TSD Script 言語は、クライアント / サーバー・アプリケーションの開発に使用する各種の SQL ステートメントおよび SQL データベースをサポートします。

直接ドライバーでサポートされていない SQL ステートメント

SQL ステートメントの一部は Oracle、Sybase/SQLServer、および Informix 直接ドライバーではサポートされていません。ステートメントはこの後のテーブルにリストされています。

This statement... Is supported only in...
SQLDeleteCurrent DB2/2
SQLGetCursorName DB2/2
SQLUpdateCurrent DB2/2

注: SQLUpdateCurrent および SQLDeleteCurrent では、ネストされたステートメントを使用する必要がありますが、可能なかぎり少ない回数だけ使用してください。ステートメントは一般的に旧式とみなされ、広範囲でサポートされなくなっています。

データ・ソース属性および説明

この項では、データ・ソースを構成する時に使用できる属性について説明します。これらの属性は Developer's Toolkit のデータベース層の動作をコントロールします。

注: データ・ソースを構成するために SQL 構成エディターを使用する時には、これらの属性は不要です。この章の後方にある 「データベースへのアプリケーションの接続」 の項を参照してください。

データベース・ソース定義

データベース・ソース とは、特定の名前によって識別される情報のコレクションです。これは、データベースおよびデータベース接続を定義するために使用されます。

注: ソース名の選択はユーザーが行なってください。TSD Script では、事前定義名は不要であり、それも認識されません。TSD Script では、数値で始まっていないデータ・ソース名が必要です。ただし、TSD Script によって作成されたアプリケーションでは、特定のソース名が必要となることがあります。たとえば、Tivoli Problem Management では、データ・ソース名として "ADVISOR" が必要となります。これらの要件については、そのアプリケーションの文書を参照してください。

ソースの属性

データ・ソースを構成する時には、そのデータ・ソースの属性または特性は ATTRIB=VALUE 構文を使用してリストされます。使用可能な属性は次の通りです。

次の属性は通常使用されません。

TSD Script はそれぞれの DBMS に対して、サポートされるデフォルトを自動的に使用します。これらの属性を使用するのは、大文字小文字の区別のインスタンスなど、特別な場合にデフォルトを上書きする場合だけです。

ほとんどの場合に、デフォルトを変更する必要がありません。これらの属性の多くはデータベースの拡張機能に影響を及ぼすので、この変更はデータベース・アドミニストレーターだけが行なわなければなりません。

CASE_CONVERSION

大文字小文字の区別のオブジェクト名をもつデータベースを使用する場合には、適切な大文字・小文字によって照会をコーディングする必要があります。データベースのすべてのオブジェクトを同じ文字 (すべて大文字またはすべて小文字) で作成した場合には、TSD Script によってすべてのオブジェクト名をその大文字小文字に変換することができます。この属性項目で使用可能な値は UPPER、LOWER、または NONE です。デフォルト値 (この項目が表示されない場合) は NONE です。

注: TSD Script は常に、照会内の引用符付き文字列リテラルの大文字小文字を保存します。

CASE_SENSITIVE

この項目は、ユーザー DBMS がデータベース・オブジェクトと関連の大文字小文字を取り扱う方法を参照します。 データベース・オブジェクトはテーブル名、列名などです。この値が TRUE の場合には、TSD Script はすべてのオブジェクト名の大文字小文字を保存します (CASE_CONVERSION を設定しないかぎり)。 CASE_SENSITIVE 項目がない場合には、デフォルト値は FALSE です。

COLUMN_DEFINITION_TABLE

次の項目は、デフォルト列のカタログ・ビューの TSD Script で必要となる列名を上書きするために使用されます。

デフォルト
COL_NAME_COLUMN NAME
COL_REMARKS_COLUMN REMARKS
COL_LENGTH_COLUMN LENGTH
COL_SCALE_COLUMN SCALE
COL_TYPE_COLUMN COLTYPE
COL_NULLS_COLUMN NULLS
COL_TBNAME_COLUMN TBNAME
COL_TBCREATOR_COLUMN TBCREATOR

注: TSD Script はそれぞれの DBMS に対して、サポートされるデフォルトを自動的に使用します。したがって、この項目は通常環境では使用されません。この項目が使用されるのは、特殊な場合のデフォルトを上書きする場合だけです。この項目には、列ディレクトリー / カタログ・テーブルまたはビュー名が含まれています。 Tivoli 製品は整合性のために「ラッパー」ビューを提供するので、デフォルト値は常に SAI_SYSCOLUMNS です。

COMMIT_SELECTS

MANUAL_COMMITS が TRUE の場合には、この項目が使用可能です。適用できる場合には、デフォルト COMMIT_SELECTS 設定は TRUE です。

選択後に自動コミットしたい場合には、COMMIT_SELECTS 項目を TRUE に設定します。

DATE_FORMAT

DATE_FORMAT はデータ・ソース (DBMS) で必要な日付形式です。ほとんどのシステムの場合に、デフォルトの日付形式は mm/dd/yyyy です。Oracle のデフォルト日付形式は dd-MON-yy です。

日、月、年、および区切り記号の形式を指定して、日付形式をカスタマイズします。これらのアイテムの組み合わせはほとんどがサポートされますが、サポートされない例外も少しあります。たとえば、yyyymmdd はサポートされますが、yyyyddmm はサポートされません。

日の指定

日および月の両方から先行ゼロを除去することができます。日の先行ゼロを除去するには、その日に 1 つの "d" だけを指定してください。

注: 日から先行ゼロを除去する場合には、月からも先行ゼロを除去しなければなりません。たとえば、 mm/d/yyyy を使用することはできません。

結果
mm/dd/yyyy 07/08/1999
m/d/yyyy 7/8/1999

月の指定

月は、カレンダー年のその月の番号によって、あるいはその月の名前 (1= 1 月) によって指定することができます。番号によって月を指定する場合には、"MM." を使用します。月の番号の先行ゼロを除去するためには、"M."を使用します。月を名前または省略形によって指定するには、"Month" or "Mon." を使用します。
月の名前の指定子は (Month と Mon の両方) では大文字小文字の区別があります。月の番号の指定子 (MM および M) では大文字小文字の区別がありません。

注: 月から先行ゼロを除去する場合には、日からも先行ゼロを除去しなければなりません。

結果
MM 08
M 8
8 月
Mon Aug
MONTH AUGUST
MON AUG

年の指定

年を指定する時には、その年を完全に、あるいはその年の最後の 2 桁だけを指定することができます。

注意: Tivoli では、2000 年の日付について 4 桁全部の数字を使用することをお奨めします。

結果
mm/dd/yyyy 07/08/1999
mm/dd/yy 07/08/99

区切り記号

日付の形式設定には、次の区切り記号を使用することができます。

区切り記号タイプ 結果
なし yyyymmdd 19990626
ピリオド mm.dd.yyyy 06.26.1999
ダッシュ dd-mm-yyyy 26-06-1999
スラッシュ mm/dd/yyyy 06/26/1999

DBMS

ODBC ドライバーでは、DBMS リストが SQL 構成ファイルに必要となります。 DBMS= 項目としてリストできる可能なデータベースは次の通りです。

DEFAULT

この値が TRUE の場合には、このデータ・ソースは接続時のデフォルト・データ・ソースとみなされます。 DEFAULT 項目を使用できるのは、SQL 構成ファイル当たり 1 つだけです。デフォルト値 (この項目が表示されない場合) は FALSE です。

DRV

これは DBMS ドライバー名であり、接続時に必要です。

DSN

この属性は SQL 構成ファイルのデータ・ソース名をリストします (ODBC のみ)。

MANUAL_COMMITS

この項目は直接インターフェースで使用することができます。すなわち、TSD Developer's Toolkit レベルでトランザクション・コントロールを操作したい場合には、これを TRUE に設定しなければなりません。

MULTIPLE_CONNECT

DBMS が複数の同時接続をサポートする場合には、この項目は TRUE に設定しなければなりません。

MULTIPLE_CONNECT_REQUIRED

同時に複数のオープン・ステートメントを実行するために DBMS で複数の接続が必要な場合 (たとえば、ネストされた選択 / 取り出しループ) には、この項目を TRUE を設定してください。Sybase および SQLServer のデフォルト値は TRUE です。この他のすべてのデータベースでは、これは FALSE です。

注: 必要な時には、TSD Script によって追加の接続がオープンされます。

QUAL

これは、テーブル・アクセスに使用される修飾子です。SQL はテーブル定義にそのテーブルの作成者 / 所有者を保管します。この作成者 / 所有者の名前は、そのテーブルの 修飾子として参照されます。 データベース中のテーブルを個別に識別するために、修飾子とテーブル名の組み合わせを使用しなければなりません。

SYSQUAL

この項目には、システム・カタログ・テーブル / ビューへのアクセスに必要な修飾子の名前が入っていなければなりません。すべての Tivoli 製品には、整合性のために "ラッパー" ビューが提供されているので、デフォルト値は現行の修飾子と同じです (デフォルト接続ストリング)。

TABLE_DEFINITION_TABLE

この項目には、列ディレクトリー / カタログ・テーブルまたはビュー名が含まれています。すべての Tivoli 製品は整合性のために "ラッパー" ビューを提供するので、デフォルト値は常に SAI_SYSCOLUMNS です。

次の 5 つの項目は、デフォルト・テーブルのカタログ・ビューの TSD Script で必要となる列名を上書きするために使用できます。

タブ名のデフォルト

TAB_NAME_COLUMN NAME
TAB_REMARKS_COLUMN REMARKS
TAB_TYPE_COLUMN TYPE
TAB_CREATOR_COLUMN CREATOR
TAB_COLCOUNT_COLUMN COLCOUNT (DB2/2 と SQLBase の場合)

TIME_FORMAT

この項目はデータ・ソースで必要な時刻形式です。すべての DBMS 項目のデフォルトは hh:mm:ss です。ほとんどの時刻形式の指定子は有効ですが、一部は有効でありません。 たとえば、hh:mm:ss はサポートされていますが、mm:hh:ss はサポートされていません。

有効な時刻形式の詳細については、TSD 6.0 Script 言語解説書TimeFormat ステートメントの項を参照してください。


軍隊時刻

デフォルトによって、時刻は軍隊時刻 (24 時間クロック) で指定されます。時刻を 12 時間クロックで指定するためには、AM_PM 接尾部を含めます。

結果
hh:mmAM_PM 09:08 PM
hh:mm 21:08

大文字小文字を区別しない時刻形式

形式指定子は大文字小文字を区別しません。たとえば、hh:mm:ss は HH:MM:SS と同じです。

先行ゼロのトリム

先行ゼロをトリムするには、h、m、および s を 1 つだけ指定してください。たとえば、次の通りです。

結果
hh:mm:ss 08:35:09
h:m:s 8:35:9

注: 先行ゼロのトリムを選択した場合には、時、分、秒から先行ゼロをトリムしなければなりません。

秒の指定

秒を指定するためには、ss 指定を含めてください。任意に秒を省略することができます。

結果
hh:mm:ss 08:35:09
h:m 8:35

区切り記号

時刻指定子を形式設定するためにコロンまたはピリオドのいずれかを指定することができます。

区切り記号タイプ 結果
なし hhmmss 121604
ピリオド hh.mm.ss 12.16.04
コロン hh:mm:ss 12:16:04

UPPERCASE_FUNCTION

この項目には、照会の列を英大文字に変換するために使用する DBMS 特定の機能名を含めます (SQLCreateSearchString で使用される)。デフォルト値は次の通りです。

データベースへのアプリケーションの接続

データベースへの接続は、すべての SQL DBMS で共通です。接続の方法は、使用するデータベースに関してそれぞれ異なります。例:

これらの相違にマスクをかけるために、TSD Script は SQLCommand ステートメントを使用する 1 セットの接続サービスを提供します。SQLCommand によって、SQL 構成ファイルの DBMS 特定の接続情報に対して外部コマンドを使用することができます。これは、アプリケーション・コードを単純化して、可搬のものにします。

SQL 構成ファイル名

Developer's Toolkit SQL 構成ファイルのデフォルト名は sai_sql.cfg です。 Developer's Toolkit は、SAI ルート・ディレクトリーの CFG サブディレクトリーで sai_sql.cfg と呼ばれるファイルを検索します。

TSD Script が検索するファイル名は、異なったファイル名を含めるために SAISQLCFG と呼ばれる環境変数を設定することによって上書きすることができます。SAISQLCFG 環境変数の値は、SAI_ROOT から取り出されるパスより優先されます (この両方が存在する場合)。 ファイルが検出されない場合には、エラーが戻されます。

SQL 構成ファイルは、データ・ソースを記述するセクションに分割されます。 データ・ソースは、ユーザーが作業している DBMS と考えられます。通常、データ・ソースは物理データベース・サーバーに相当しますが、サーバー内の論理ソースも含めて考えるように拡大されます (たとえば、データベース当たり 1 つのデータ・ソース)。

構成命令の他の位置

Developer's Toolkit は、ユーザーのデータベース要件に基づいて使用できる多くの直接データベース・インターフェースを提供します。これらの直接データベース・インターフェースは、Developer's Toolkit のデータベース接続のデフォルトのメソッドです。

直接データベース・インターフェースではなく、ODBC を使用したい場合、ODBC ドライバーの詳細については、Tivoli Service Desk 6.0 インストールの手引きの付録 A の" ODBC 構成"で調べることができます。

デフォルトの Developer's Toolkit 直接データベース・インターフェースを使用する場合、完全な構成およびテスト命令については、 Tivoli Service Desk 6.0 インストールの手引き の "構成処理" を参照してください。

データベース構成の例

データベース・クライアントを初めて使用するためにこれを追加するには、次のステップに従ってください。

  1. Developer's Toolkit プログラム・グループから、SQL 構成エディターを選択します。
    結果: 「SQL 構成エディター」ダイアログ・ボックスが現れます。

次のコンポーネントが 「SQL 構成エディター」ダイアログ・ボックスで検索されます。

  1. これが「ファイル」テキスト・ボックスにまだ入力されていない場合には、sai_sql.cfg ファイルのドライブ、パス、およびファイル名 (デフォルト位置は c:\sai\cfg\sai_sql.cfg) を入力して「追加」を選択してください。
    結果: 構成ファイルが作成されて、最初のデータ・ソースが追加されました。「ドライバー選択」ダイアログ・ボックスが表示されます。
  2. 使用したいデータベース・ドライバーをラジオ・ボタン・リストから選択して、「了解」を選択します。
    結果: 「ソース・セットアップ」ダイアログ・ボックスが表示されます。
  3. データベース・クライアントと関係のある情報を該当のテキスト・ボックスに入力して、「了解」または「拡張」を選択してください。

結果: 「了解」を選択した場合には、プロシージャーによって完了されます。「ソース・セットアップ」ダイアログ・ボックスから「拡張」を選択した場合には、「拡張オプションのセットアップ」ダイアログ・ボックスが表示されます。

  1. 「追加」を選択します。
    結果: 「オプションの選択」ダイアログ・ボックスが表示されます。
  2. 構成したいオプションを選択して、「選択」を選択してください。
    結果: 「オプション値の入力」ダイアログ・ボックスが表示されます。
  3. 「オプション値の入力」ダイアログ・ボックスでは、構成しているソースの属性オプションおよび属性値を入力します。詳細情報が必要な場合には、「ヘルプ」を選択してください。
  4. 「了解」を選択して、「SQL 構成エディター」を終了します。

データベース・クライアント接続のテスト

新規のデータベース接続を追加した後、その構成をテストして、それが適切に作動しているかどうかを確認しなければなりません。データベース接続をテストするには、次のステップを完了してください。

  1. Developer's Toolkit プログラム・グループから、SQL 構成エディターを選択します。
  2. テストしたいデータ・ソースを選択して、「接続のテスト」を選択します。「接続のテスト」機能がエラー・メッセージを戻した場合には、「ソース・セットアップ」ダイアログ・ボックスに入力したパラメーターを検査するか、あるいはその接続をテストしてください。

SQL 構成ファイルの接続情報

ユーザー ID およびパスワードを SQL 構成ファイルに保持する場合には、セキュリティーに問題があることがあります。また、このファイルにはすべてのユーザーが容易にアクセスできて、保管されるパスワードはデフォルトによって暗号化されされないので、複数のユーザーについて接続固有の情報を保持する場合も、難しい問題がある場合があります。
ユーザーは SQL 構成エディターを使用して暗号化を選択する必要があります。詳細については、本書のデータベース構成の例 を参照してください。

TSD Script には、接続ステートメント自身に接続固有の情報を提供する簡単な方法があります。

ret := SQLCommand('CONNECT SOURCE=DB2_TEST;
UID=FRED; PWD=DERF;'); 

TSD Script がこのタイプの接続要求を検出すると、次のことが行なわれます。

DB2_TEST のデフォルト接続ストリングが位置指定されます (DB2_TEST は SQL 構成ファイルのソースでなければならない)。SOURCE= 項目が見つからない場合には、TSD Script はデフォルトを使用します。

注: 他の属性が存在する場合には、データ・ソース名の前に SOURCE= を書き込む必要があります。

新規の接続ストリングのフォーム設定は、デフォルト接続ストリングの対応する項目上に残りの ATTRIBUTE=VALUE の対をオーバーレーし、さらにデフォルト接続ストリングにない新規の対を挿入することによって実行されます。

ドライバー (DRV=) を除き、デフォルト接続ストリングの項目を上書きすることができます。これによって、必要に応じて上書きできるデフォルト接続情報 (データベース、テーブル修飾子など) をもつことができます。また、新規のデータ・ソース (データベース当たりのソースなど) を作成することによっても、この一部を実行することができます。

SQL 構成ファイルの除去

SQLCommand に対してすべての接続情報を提供し、SQL 構成ファイルを除去することができます。ただし、すべてのデフォルト・ソース値 (MULTI_CONNECT など) を受け入れるようにしなければなりません。

通常、DBMS 特定の情報を外部化することをお奨めします。ただし、SQL 構成ファイルを除去する必要がある場合があります。それらの場合を取り扱うには、次の通り TSD Script によって、SQL 構成ファイルで検出されない新規のソースに接続して登録することができます。

ret := SQLCommand('CONNECT NEWSOURCE=MYAPP; 
                   DRV=XOORA;SRVR=X:ORASERV; 
                   UID=MARY; PWD='); 

サンプル・データベース

データベース・テーブルとビュー

この章ではこの後、COMPANY と呼ばれるサンプル・データベースについて説明します。 このデータベースは次のテーブルとビューから構成されています。列の属性は、それぞれのテーブルまたはビュー名の下にリストされています。

テーブル DEPARTMENT

テーブル EMPLOYEE

テーブル MANAGER

SQLSelectInto によるデータの検索

SQLSelectInto

SQLSelectInto ステートメントには、SQL テーブルまたはビューから情報を取り出す簡単な方法があります。これは、引き数の変数番号を使用します。

最初の引き数

最初の引き数は常に、次のような SQLSelect ステートメントを表す文字列式となります。

SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID='305-83-3811'. 

ほとんどの場合、SQLSelectInto を使用して、テーブルから固有の行を検索します。最初の引き数として渡される選択式には、次の形式の文節が含まれています。

WHERE <primary-key>=<value> 

一般に、選択ステートメントの形式は次の通りです。

SELECT <column-list> FROM <table-or-view name> WHERE <condition>. 

<column-list> は、コンマで区切られた 1 つまたは複数の列名のリストです ("FIRST_NAME, LAST_NAME" など)。1 つのテーブルからすべての列を取り出したい場合には、アスタリスク (*) を使用することができます。

<condition> は、列名、関係演算子 (=, >, <, >=, <=)、および値 ('SMITH' など) を使用して通常フォーム設定される TRUE/FALSE 条件です。

有効な選択ステートメントの例は次の通りです。

SELECT EMPLOYEE_ID,LAST_NAME FROM EMPLOYEE WHERE 
    DEPARTMENT_ID='SALES' 
SELECT FIRST_NAME,LAST_NAME,PHONE FROM EMPLOYEE 
SELECT * FROM MANAGER 

それ以降の引き数

SQLSelectInto に次ぐ 2 番目およびそれ以降の引き数は TSD Script 変数です。これらの変数の名前は、この例に示されている通り、アクセスしている SQL テーブルまたはビューの列の名前と一致していなければなりません。

VARIABLES
  last_name, first_name: String;
ACTIONS
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM
               EMPLOYEE WHERE EMPLOYEE_ID=123',
               last_name,first_name); 

これらの例の処理では、TSD Script 変数の大文字小文字の区別は重要ではありません。 LAST_NAME 列からの値は、last_name ストリング変数に読み込まれます。 FIRST_NAME 列からの値は、first_name ストリング変数に読み込まれます。

レコード変数の使用法

SQL テーブルから情報を取り出す簡単な方法は、TSD Script レコード変数を使用することです。フィールドが SQL テーブルの列名と一致するレコード・タイプを定義します。 その後で、次の通りそのタイプのレコードを SQLSelectInto に渡すことができます。

TYPES 
  EmployeeRec IS RECORD 
    employee_ID: Integer; 
    last_name: String; 
    first_name: String; 
    birth_date: Date; 
    salary: Real; 
  END; 
VARIABLES 
  r: EmployeeRec; 
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM 
                EMPLOYEE WHERE EMPLOYEE_ID=123',r);


レコード・タイプ

一般に、その名前がデータベースのすべてのテーブルまたはビューで同じレコード・タイプを宣言します。 TSD Script の 名前の結び付け 機能を使用することによって、そのレコード・タイプの変数を使用してデータベースとの間で情報の取り出しまたは挿入を行なうことができます。

前の例では、EmployeeRec レコード・タイプは、そのフィールド名とタイプが EMPLOYEE SQL テーブルの列の名前とタイプに一致するように宣言されます。 このタイプのレコード (r) を SQLSelectInto に渡すと、 Developer's Toolkit は要求された行から突き合わせフィールドに情報を自動的にコピーします。 SQLSelectInto を実行した後、r は次の値をとります。

r.employee_ID = $Unknown 
r.last_name = 'Brown' 
r.first_name = 'Robert' 
r.birth_date = $Unknown 
r.salary = $Unknown 

r.LAST_NAMEr.FIRST_NAME の列だけが値をもつことに注意してください。レコードのすべてのフィールドは値 $Unknown から始まります。 SQLSelectInto ステートメントは LAST_NAMEFIRST_NAME の列を選択したので、r.LAST_NAMEr.FIRST_NAME だけに値が割り当てられています。 次のステートメントが使用された場合に、すべての r フィールドが完了します。

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID=123',r); 

TSD Script Import ステートメントの使用法

TSD Script レコード・タイプと SQL テーブルとの間のマッピングは直観的な処理です。TSD Script では、import ステートメントの方法によってテーブル、ビュー、およびレコード・タイプの間で自動的関連付けを作成することができます。

これは、テーブルまたはビューのすべての列に対してレコード・フィールドを手動で宣言する必要がない、ことを表します。次の例を見てみましょう。

TYPES
  EmployeeRec IS RECORD 
    IMPORT('EMPLOYEE'); 
  END; 

Import ステートメント

Import ステートメントをレコード宣言の内部で使用して、SQL テーブルまたはビューの名前およびタイプからフィールド宣言を直接作成することができます。
テーブルまたはビューが変更された場合には、レコード宣言はその変更を自動的に追跡します。 すなわち、新規の ADDRESS 列を EMPLOYEE テーブルに追加した場合には、新規の

address: String; 

フィールドを EmployeeRec に追加する必要はありません。 IMPORT は時刻解析ステートメントです。 IMPORT ステートメントを含むモジュールが再ビルドされる (parsed) と、指示された SQL テーブルまたはビューが読み取られて、その列がフィールド宣言の作成に使用されます。

接続ストリング

Import ステートメントには、テーブルまたはビュー名と一緒に指定される接続ストリングがあります。この接続ストリングは、 sai_sql.cfg ファイルに指定されたデフォルト接続ストリングを置き換えます。逆方向の互換性のために、'DATABASE xxx' の形式のデータベース名を指定することができ、ここの xxx はデータベースの名前です。

/S オプションによる構文解析

解析時には、/S オプションを TSD Script Parser に渡して、import ステートメントのハード・コーディング・データベースまたは接続情報を上書きする必要があります。

/S オプションによって、データ・ソース名をハード・コーディングする必要がないように、解析時にデータベースを指定することができます。また、これによって、コマンド・プロンプトから TSD Script Parser を実行します。これらの値は、sai_sql.cfg ファイルに指定されたデフォルトの代わりに使用されます。

/S オプションを使用するときの優先メソッドは、sai_sql.cfg ファイルのユーザー ID およびパスワードを除いて、すべての値を指定することです。その後で、解析の時に、これらの値を渡すことができます。例:

/S"UID=UserId;PWD=Password" 

(この場合の UserId はユーザー ID であり、Password はユーザー固有のパスワードです。)

キーワードの使用法

IMPORT を使用する時には、任意指定のキーワードを使用して、IMPORT の目次の順序付けを明白にすることができます。それらのキーワードは次の通りです。

キーワードをどれも指定しない場合には、インポート・ストリングの順序は、まず初めにテーブル名があり、その後に接続ストリングが続いているとみなされます。

空白文字またはコンマ (あるいはこの両方) を使用して、テーブル名と接続情報を区切ります。

注: TABLE または VIEW のいずれかのキーワードを使用して、テーブル名またはビュー名を識別することができます。これらは同様に取り扱われます。

本書では、キーワードはすべて大文字で表示され、大文字小文字の区別は行われません。 ただし、テーブル名および接続情報は、DBMS のインストールによっては大文字小文字の区別が行われることがあります。この情報については、 LAN アドミニストレーターまたはデータベース・アドミニストレーターのいずれかと一緒にチェックしてください。また、大文字小文字の区別が問題になるかどうかを確認するために、DBMS に付いてきた解説書を調べることもできます。

IMPORT ステートメントの例

有効なインポート・ストリングをビルドする方法はいくつかあります。次の例は、ユーザーに各種の選択項目を提供するために設計されています。ただし、1 つのスタイルを選択し、一貫してそれを使用することをお奨めします。

IMPORT を優先使用するメソッドは次の通りです。

Import('ALARMS'); 

次の構文は SA-ASE 4.1 でサポートされていました。

Import('DATABASE ADVISOR TABLE ALARMS');

SA-ASE 4.2 およびそれ以降では、この構文は次の通りです。

'CONNECT DB=ADVISOR' 

次の例も、前の例と同じです。

Import ('CONNECT DB=ADVISOR TABLE ALARMS'); 
Import('TABLE ALARMS CONNECT DB=ADVISOR'); 
Import('ALARMS, CONNECT'); 
Import('TABLE ALARMS'); 
Import('VIEW PROBLEM_VIEW'); 

次の例には、接続ストリングの内部にスペースが欠落していることに注意してください。

Import('ALARMS, SRVR=X:ORASRV;DB=ADVISOR'); 

また、次も正しい例です。

Import('TABLE ALARMS, CONNECT SRVR=X:ORASRV; DB=ADVISOR); 

次の例では、"'" は任意指定です。

Import('TABLE ALARMS CONNECT SRVR=X:ORASRV; DB=ADVISOR'); 

また、次も正しい例です。

Import('CONNECT SOURCE=ADVTEST;SRVR=X:ORASRV; DB=ADVISOR, TABLE ALARMS);

間違った例

'ADVISOR' が有効な接続ストリングでない ('DB=ADVISOR' は有効な接続ストリング) ために、次の構文は間違っていることに注意してください。

Import('ALARMS,ADVISOR'); (*this is WRONG!*)

データ・タイプ

TSD Script には、次の 6 つの単純データ・タイプがあります。

IMPORT ステートメントは、これらのデータ・タイプに基づいて列をフィールドにマップする一般の方法をとります。

マップ先...
CHAR、VARCHAR、および LONG VARCHAR TSD Script STRINGS
INTEGER TSD Script INTEGERS
DATE TSD Script DATES
TIME TSD Script TIMES
10 進小数点を含む SQL タイプ (固定または浮動) TSD Script REALS

BOOLEAN タイプはほとんどの SQL 実装でサポートされていません。ただし、 Oracle または IBM の DB2/2 を使用する場合には、列のコメントに $ASETYPE=BOOLEAN を含めて、IMPORT ステートメントのある Boolean フィールドを生成することができます。SQLServer では、Developer's Toolkit がユーザー定義の BOOLEAN タイプを作成します。

Developer's Toolkit は Informix の SYSCOLUMNS ビューにリンクするタイプのテーブルを作成します。


複数行の検索

SQLSelectInto は、テーブルまたはビューから固有の行を検索するための簡単な方法です。 SQLSelectInto は 1 行の検索には使用できますが、テーブルのスキャンはできません。

TSD Script は、ループ内のデータベースから複数のアイテムを検索するためのカーソル変数を提供します。カーソルは検索されたリストの現在位置を記憶しています。

処理

複数行を検索するための基本処理は次の通りです。

複数行の検索を許可するために、TSD Script は次の 3 つのステートメントを提供します。

TSD 6.0 Developer's Toolkit Script 言語解説書 には、上記のステートメントに関する詳細情報が示されています。

このステートメントは次の例で使用されています。

VARIABLES 
  cursor: SQLCursor; 
  r: EmployeeRec; 
ACTIONS 
 IF SQLSelect(cursor,'SELECT * FROM EMPLOYEE WHERE 
              SALARY>>0000.00') > 0 THEN 
    WHILE SQLFetch(cursor,r) > 0 DO 
      ProcessEmployee(r); 
    END; 
    SQLCloseCursor(cursor); 
 END; 

この例では、次のことが行われます。

SQLCloseCursor の操作はとても重要です。SQL カーソルがオープンされると、ほとんどの SQL 実装では結果テーブルのすべての行をロックします。これらの行は、SQLCloseCursor ステートメントが処理されるまでロック解除されません。

注: 一般に、ユーザーは SQLSelectSQLCloseCursor とのステートメント間のユーザー・インターフェース操作の実行を望みません。さらに、TSD Script では、同時のカーソル数が制限されます。カーソルのクローズを忘れた場合には、結果としてこの制限を超えることになります。

修飾子

修飾子の使用法

SQL によって 1 つのデータベース内で同じ名前の複数のテーブルを使用することができます。これらを区別するために、SQL はテーブル定義にそのテーブルの作成者 / 所有者を保管します。この作成者 / 所有者の名前は、そのテーブルの修飾子として参照されます。データベース中のテーブルを個別に識別するために、修飾子とテーブル名の組み合わせを使用しなければなりません。例:

mary.address

ほとんどの SQL データベース管理プログラムは、なにも指定されない場合に、現行ユーザーの IDを修飾子として使用します。そのデータベースを作成したユーザーとしてログオンしていないで、修飾子も提供しない場合には、特定の SQL 実装では、修飾子としてデータベース所有者を使用してデータベースの検索が続行されます。その他の SQL 実装 (DB2/2 など) では、その都度修飾子を提供しなければなりません。

修飾の置き換え

TSD Script は、接続ストリングに QUAL= 項目を提供しないかぎり、適切な修飾の置き換えを実行します。

TSD Script は、次を除いて、すべてのステートメントで置き換えを実行します。

相関名を含む複雑な照会を使用する場合には、適切な置き換えが行なわれないことがあります。これらの場合を処理するために、 TSD Script は疑似修飾子 $QUAL を提供し、これが現行の修飾子の代わりに置き換えられます (すなわち、接続ストリングの QUAL= 項目によって設定されたもの)。

たとえば、修飾子のハード・コーディングを回避するために、次のコード・フラグメントは修飾子として $QUAL を使用します。

ret := SQLExecuteImmediate('DROP TABLE $QUAL.ADDRESS'); 

引用符

TSD Script では、すべてのストリングは単一引用符 (またはアポストロフィ) で囲まれます。また、 SQL では文字、日付、および時刻のリテラルも単一引用符で囲まなければなりません。たとえば、次のような SQL 照会を出すには、

SELECT * FROM EMPLOYEE WHERE LAST_NAME = 'BROWN' 

以下の TSD Script ステートメントを使用することになります。

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE
LAST_NAME=''BROWN''',r); 

上記の SQLSelectInto の例では、"BROWN" の "B" の左の 2 つの単一引用符が結果的に 1 つの単一引用符となることが分かります。"BROWN" の "N" の後に 2 つの単一引用符があります。この結果、1 つの単一引用符がその位置に挿入されます。"BROWN" の "N" の後の 3 番目の単一引用符は、ストリングを終了するために使用されます。

TSD Script 文字列リテラルに単一引用符を組み込むためには、2 つの単一引用符を組み込む必要があります。たとえば、ストリング "Tom's Place" を TSD Script 変数に割り当てるには、次を使用しなければなりません。

s := 'Tom''s Place';

文字列と引用符との連結

引用符を使用する文字列の連結では、これはさらに複雑になります。この例では、実際に検索したい姓は、last_name と呼ばれるストリング変数に保管されます。

last_name := 'BROWN'; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
             LAST_NAME=''' & last_name & '''',r); 

TSD Script 連結演算子 (&) を使用して select ストリングを作成する時には、検索したいリテラル値の片側に単一引用符を入れることに注意してください。結果の照会は次のようになります。

SELECT * FROM EMPLOYEE WHERE LAST_NAME = 'BROWN' 

姓値の左の単一引用符は、"LAST_NAME='' の後の 3 つの単一引用符を介して行われます。

これらの最初の 2 つは、必要な単一引用符を挿入するために使用され、3 番目のものは、単に最初のストリング定数 'SELECT * ... ='を終了しています。

2 番目に必要な単一引用符は、リテラル '''' を式全体の終わりに連結することによって行われます。

検索される値がストリング、日付、または時刻である選択式を作成する時には、検索値をもつ変数の前に 3 つの引用符を、その後には 4 つの引用符を挿入しなければなりません。

例外

他のタイプのデータを検索する場合には、次の通り引用符は不要です。

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
              AGE=30',r); 

30 は整数値であるので、これを引用符で囲む必要があります。30 が整変数内に入っている場合には、そのステートメントは次のようになります。

age := 30; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE AGE=' & age,r);

SQLFormat ステートメントによるデータ・フォーマット

SQLFormat の使用法

SQLFormat ステートメントは、SQL 操作で使用される TSD Script ステートメントです。 SQLFormat は、現在使用中の DBMS のデータ形式と一致する文字列にデータ値を変換します。

SQLFormat ステートメントは、日付および時刻の変数の場合に特に有用であり、次の構文を使用します。

SQLFormat(value: SIMPLE EXPRESSION): STRING;

注: ユーザーの DBMS では、Developer's Toolkit による表示に使用されるデフォルト形式とは異なった日付および時刻形式が必要となることがあります。たとえば、デフォルトの Oracle 日付形式は DD-MON-YY ですが、デフォルトの Developer's Toolkit 日付形式は MM/DD/YYYYです。

SQLFormat がとる値の引き数は、DATE または STRING などの単純なタイプでなければなりません。 SQLFormat は、戻りコードではなくて、書式制御ストリングを戻し、これは、操作が正常に実行されたかどうかを指示します。渡された値が $Unknown の場合には、文字列 'NULL' が戻されます。文字列の特定の形式設定は、その文字列のタイプによって異なります。

SQLFormat の使用の知識ベースは次の通りです。

KNOWLEDGEBASE の例;
--PUBLIC 
ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER; 
PRIVATE 
ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER IS 
 VARIABLES 
   retCd : INTEGER; 
   cmd : STRING; 
   $SQLColumn_1 : INTEGER; 
 ACTIONS 
   cmd := 'SELECT COUNT(*) FROM COMPANIES WHERE name = 
          ' & SQLFormat('Joe''s place') & 
          ' AND founded_date='& SQLFormat(d); 
   retCd := SQLSelectInto(cmd, $SQLColumn_1); 
   IF retCd < 0 THEN 
     Exit( retCd ); 
   ELSE 
     Exit( $SQLColumn_1 ); 
END; 
 END; 

データ形式で使用される TSD Script ステートメントの詳細については、TSD 6.0 Developer's Toolkit Script 言語解説書を参照してください。

名前の上書き

TSD Script は変数名および列名の等価を使用して、データ検索を簡素なものにします。時刻がありますが、これは、名前基本マッピングが不便で、使用できない場合です。

EMPLOYEE テーブルで従業員数 (行数) の判別に使用できる次の SQL 照会を考えてみましょう。

SELECT COUNT(*) FROM EMPLOYEE

名前の突き合わせなしのデータの検索

TSD Script は、名前の突き合わせなしで SQL 列からデータを検索する簡単な方法を提供します。ユーザーが実行しなければならないことは、$SQLCOLUMN_n の名前の変数を宣言することで、この場合の "n" は、ユーザーが検索したい列数です。この変数のタイプは、検索中の列にマップしなければなりません。

EMPLOYEE テーブルで従業員数 (行数) を検索するには、次のコーディングを使用することができます。

VARIABLES
  $SQLCOLUMN_1: INTEGER;
ACTIONS
  SQLSelectInto('SELECT COUNT(*) FROM
                 EMPLOYEE',$SQLCOLUMN_1);

$SQLCOLUMN_1 は通常の変数です。これを割り当て、テストして、式などで使用することができます。

データの更新

概要

この項では、データを SQL データベースに挿入し、SQL データベースからデータを削除し、SQL データベースのデータを変更する方法を説明します。

データの挿入

SQLInsert ステートメントを使用して、テーブルに新規の行を挿入することができます。 ユーザーが実行しなければならないことは、テーブル名の後に、挿入したいデータを含む変数を続けて指定することだけです。検索機能と同様に、TSD Script は TSD Script 変数名と SQL 列名との間のマッピングを実行します。

次の例では、タイプ EmployeeRecord の変数の変数フィールドに値が割り当てられます。このステートメントを EMPLOYEE テーブルに挿入するには、宛先テーブルの名前および変数によって SQLInsert を呼び出します。

VARIABLE 
  r: EmployeeRecord; 
ACTIONS 
  r.employee_ID:'312-34-3444'; 
  r.last_name:'Brown' 
  r.first_name:'Robert' 
  r.birth_date:'08/05/1964'; 
  r.salary:  $Unknown 
  SQLInsert('EMPLOYEE',r); 

SQLInsert は、SQLSelectInto および SQLSelect と同様に、引き数の変数番号を使用します。 最初の引き数がテーブルの名前です。残りの引き数は、新規行の各列に書き込むための値を示します。次の例に示されている通り、単一レコードまたは多くの単純変数を渡すことができます。

VARIABLE
  employee_ID: STRING; 
  last_name: STRING; 
  first_name: STRING; 
  birth_date: DATE; 
  salary: REAL; 
ACTIONS 
  employee_ID:'312-34-3444'; 
  last_name:'Brown'; 
  first_name:'Robert'; 
  birth_date:'08/05/1964'; 
  salary:$Unknown; 
  SQLInsert('EMPLOYEE',employee_ID,last_name,
            first_name,birth_date,salary); 

データの削除

SQLDelete を使用して、1 つまたは複数の行をテーブルから削除することができます。これには、2 つの引き数があります。すなわち、テーブルの名前と、削除する行を識別する SQL WHERE 文節です。この文節の語 WHERE は任意指定です。

この例では、その姓が "Smith." であるすべての従業員を削除します。

SQLDelete('EMPLOYEE','LAST_NAME=''Smith'''); 

次の例は、特定の従業員 ID 番号をもつすべての従業員を削除します。

SQLDelete('EMPLOYEE','EMPLOYEE_ID=''123-45-
           6789''');

データの変更

SQLUpdate を使用して、テーブルの既存の行に保管された情報を変更することができます。このステートメントには、次の引き数があります。

たとえば、10% の昇給を受けた 345-67-8901 の ID をもつ従業員が会社にいるものとします。その事実を反映させるために、次の通りデータベースを更新します。

VARIABLES 
  salary: REAL; 
ACTIONS 
  IF SQLSelectInto('SELECT SALARY FROM EMPLOYEE 
                  WHERE EMPLOYEE_ID=
                  ''345-67-8901''', 
                  salary) > 0 THEN 
  salary := salary * 1.10; 
  SQLUpdate('EMPLOYEE','EMPLOYEE_ID='
            '345-67- 8901''',salary); 
END; 

次の例では、会社はすべての従業員に対して 10% の昇給を認めることを決定しました。この例では、その情報によってデータベースを更新する方法が示されています。

VARIABLES 
  salary: REAL; 
  cursor: SQLCursor; 
ACTIONS 
  IF SQLSelect(cursor, 
               'SELECT SALARY FROM EMPLOYEE 
               ') > 0 THEN 
    WHILE SQLFetch(cursor,salary) > 0 DO 
      salary := salary * 1.10; 
      SQLUpdateCurrent(cursor,salary); 
    END; 
    SQLCloseCursor(cursor); 
  END; 

SQLUpdateCurrentSQLUpdate の特別のバージョンであり、これを使用して、カーソルの最後の取り出し行を更新することができます。これは、更新されるカーソル変数および値を引き数として使用します。

最後に、SQLUpdate (および SQLUpdateCurrent) は、一連の少数単純変数の代わりに、レコードを使用することができます。次の例では、以下を想定しています。

VARIABLE 
  r: EmployeeRecord; 
ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE 
                   WHERE EMPLOYEE_ID=''' & 
                   r.employee_ID & '''',r) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & '''',r);
  END; 

まとめでは、次のステップがこの例で実行されます。

受動並行性

この例ではレコードはロックされず、また同じレコードに複数ユーザーがアクセスことを禁止するステップもないことにお気付きのことと思います。

Developer's Toolkit の受動並行性機能は、複数ユーザーのアプリケーションが直面する典型的な並行性の問題を処理します。

エラー・メッセージには、否定のエラー・コードがあります。場合によっては、このエラー・コードをテストして、その値によって別のアクションを実行したい場合があります。

たとえば、コードの 1 つのセクションが挿入操作の成功に依存している場合には、そのコードを、 SQLInsert からの肯定戻りのテストで囲む必要があります。

Developer's Toolkit は、削除を試みた 2 番目のユーザーに対するエラー・メッセージを生成します。

注: 受動並行性の検査を実装するには、追加の引き数を SQLUpdate に組み込んでください。

次の例を考えてください。

VARIABLE 
  r, oldR: EmployeeRecord; 
ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
                    EMPLOYEE_ID=''' & r.employee_ID 
                    & '''', r, oldR) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & 
              '''',r,oldR); 
  END; 

この例では、次の事象が起こりました。

TSD Script が SQLUpdate ステートメントの処理を開始すると、余分なレコード変数 oldR が検出されます。これによって、次が行なわれることになります。

何らかの相違が検出された場合には、他の誰かがその行を変更して、更新が取り消されたことを表します。 SQLUpdate は否定のエラー・メッセージを戻し、ユーザー・レベルのエラー・メッセージが画面に表示されます。さらに、その行の現行値が oldR に入れられます (したがって、ユーザーはレコードの現行バージョンを検索する必要がなくなります)。

受動並行性は、複数ユーザー環境で適切な操作を確実に行なうための使いやすい効率的な方法を示します。更新される行の 2 番目の検索があるために、オーバーヘッドが少なくて済みます。ただし、提供される追加保護は値打ちがあります。

注: 一般に、更新の逸失の可能性がないことが確実でないかぎり、常に SQLUpdate の形式の受動並行性を使用する必要があります。

トランザクション指向処理

ほとんどの SQL データベース・エンジンは、複数の SQL 操作を作業単位にまとめることができる機能を提供します。その後で、組み込み機能を使用して、各作業単位が全体として成功したか、あるいは全体として失敗したかを確認することができます。

通常処理では、変更が行なわれた時に、即時にその変更がすべてデータベースにコミットされます。 トランザクション指向処理では、データに対する変更は、それぞれ別個に取り扱われます。

説明

SQLBeginWork ステートメントは作業単位の開始を示します。 SQLBeginWork は、 SQLCommit または SQLRollback のどちらかの呼び出しをユーザーが通知するまで、SQL データベース・エンジンがこのいずれも呼び出す必要がないことを、SQL データベース・エンジンに指示します。

SQLCommit ステートメントは、最後の SQLBeginWork 以降のデータベースに対するすべての変更をデータベースに適用して、その変更を永続にする必要があることを示します。

作業単位に定義された処理の 1 つが失敗した時に、SQLRollback 操作が行われます。 SQLRollback は、最後の SQLBeginWork 以降のデータベースに対するすべての変更をやり直す必要があることを示します。

たとえば、銀行用アプリケーションでは、顧客の普通預金口座から当座預金口座に送金を行なうことができます。このような転送には、1 つのテーブル (SAVINGS_ACCOUNTS) の残高の列を減少して、別のテーブル (CHECKING_ACCOUNTS) でそれを増加することが含まれます。これは、1 つの操作が成功しても、もう 1 つが失敗した場合には問題となります。その可能性を回避するためには、トランザクション指向アプリケーションでは、次の通り実行されます。

この後のコード・フラグメントは、上記で説明した原理を示しています。示されている通り、これはデータベースへの変更をコミットする前に、幾つかの SQL 操作で成功する必要がある場合です。特に、2 番目の更新が失敗した場合には、顧客は少ない貯蓄残高のままとなり、無報酬で当座預金残高を増加するので、最初の更新後にコミットしたくありません。

PROCEDURE SavingsToCheckingTransfer( 
  VAL savings_ID: STRING, 
  VAL checking_ID: STRING, 
  VAL amount: REAL) IS 
VARIABLES 
  debited, credited: BOOLEAN; 
  balance: REAL; 
ACTIONS 
  SQLBeginWork; 
  debited := FALSE; 
   IF SQLSelectInto('SELECT BALANCE FROM 
                     SAVINGS WHERE ACCOUNT_ID=''' &
                     savings_ID & ''''  
                     ,balance) > 0 THEN 
   balance := balance - amount; 
   IF SQLUpdate('SAVINGS', 
                'ACCOUNT_ID=''' & savings_ID & 
                '''', balance) > 0 THEN 
     debited := TRUE; 
  END; 
  END; 
  IF debited THEN 
    credited := FALSE; 
    IF SQLSelectInto('SELECT BALANCE FROM CHECKING 
                      WHERE ACCOUNT_ID=''' & 
                     checking_ID & '''',balance) > 
                     0 THEN 
      balance := balance + amount; 
  IF SQLUpdate('CHECKING', 
               'ACCOUNT_ID=''' & checking_ID & 
              '''' , 
               balance) > 0 THEN 
      credited := TRUE; 
    END; 
  END; 
  IF credited THEN 
    SQLCommit; 
  ELSE 
    SQLRollback; 
  END; 
 END; 
END; 

SQL 列の不明の値

空値の使用法

データベースを定義する時には、各列に空値を入れることができるかどうかを指定することができます。列に空値を入れることができると宣言すると、その列に値を入れる必要がないことを表します。 (これは、空ストリング値をもつこととは異なります。)

注: SQL の NULL は不明値の TSD Script のサポートに完全にマップされます。 TSD Script では、すべての変数は値 $Unknown で開始します。この例はレコード変数です。すなわち、レコード変数のすべてのフィールドは値 $Unknown で開始します。

不明の値のマップ

値は TSD Script と SQL の間で交換されるので、$Unknown と NULL の間のマッピングは保存されます。 たとえば、次の例で考えてみましょう。

SQLInsert('EMPLOYEE',r); 

この例では、r.salary が $Unknown の場合には、挿入される行の SALARY 列には NULL 値が含まれます。

このように、PHONE 列が指定された行で NULL であった場合には、SQLSelectInto または SQLSelect/SQLFetch のレコード変数にその行を回復することは、その変数の電話フィールドは $Unknown となります。

Developer's Toolkit フォーム・システムでは、空値もサポートされます。ユーザーがダイアログ・フィールドをブランクのままにした場合には、対応するレコード・フィールドは $Unknown に設定されます。

注: 空値の受け入れが宣言されなかった列に $Unknown 値を挿入しようとした場合には、エラーを受け取ります。これは通常、フォーム・フィールドをブランクのままにした時にかぎり起こります。

エラー処理

業務アプリケーションでは、大量のコードを作成して、エラー条件を操作します。 コードを作成した場合には、それをテストしなければなりません。これは、各ステートメントからの戻りコードを評価することを意味します。

Developer's Toolkit には、エラー処理の重荷を軽減する自動エラー処理機構が含まれています。これは、次のことを意味します。

エラー・メッセージの検出

デフォルトによって、Developer's Toolkit は不成功の SQL 操作を検出して、エンド・ユーザーに対してエラー・メッセージを表示します。

Developer's Toolkit はできるだけ多くの前後関係を表示して、エラーの原因 (重複列のエラー、入出力エラー、ディスク満杯など) を識別します。操作の成功または失敗が重要でない場合には、戻り値を検査する必要はありません。この場合、新規の従業員は EMPLOYEE テーブルに挿入されます。

SQLInsert('EMPLOYEE',r);

エラー・メッセージのフィルター処理

自動エラー・メッセージ機能を一時的に使用不可にしたい場合があります。 $ErrorFilter は、エラー・レベルしきい値を指定できるシステム整数関数です。指定されたしきい値より低いレベルのエラーはエラー・メッセージを生成しません。

次の重大度レベルは自動エラー・コード・メッセージを生成します。

エラー重大度コード 説明
0 致命的エラー
1 非致命的エラー
2 警告メッセージ
3 通知メッセージ

たとえば、$ErrorFilter(3) の設定では、3 またはそれ以下の重大度コード・レベルのエラーおよび警告だけが自動メッセージを生成することを表します。重大度コード・レベルが高いエラーでは、エラー・メッセージが表示されず、ステートメント戻りコードの試験を介してのみ認識することができます。

重大度コード・レベルは、重大度が高くなると小さくなります。したがって、致命エラー・メッセージを除いて、他のすべてを使用不可にするためには、ErrorFilter(0) を呼び出すことができます。

複数実行でのコマンドの使用法

SQL ループ・コマンドの準備

1 つの SQL コマンドをループ内で複数回実行する計画がある場合には、そのコマンドをループの外側で準備 (事前コンパイル) してから、そのループ内で準備されたフォームを実行すると、より効率的となることがあります。

Developer's Toolkit によって、ほとんどの SQL コマンドを準備できますが、動的に準備できない Select ステートメントおよびコマンドは例外です。 動的に準備できない特定コマンドの詳細については、SQL 文書を参照してください。

Developer's Toolkit は、SQL コマンドを準備するための次の 2 つのコマンドを提供します。

注: SQLPrepareSQLExecute がサポートされるのは、 DB2/2、DB2/6000、および Oracle の場合だけです。

SQLPrepareSQLExecute を使用することは、 SQLExecuteImmediate を使用するのと同じですが、必要になるまでその実行が据え置かれる点が異なります。 次の例には、SQLPrepare/SQLExecute の組み合わせによって新規ユーザーのリストを USER テーブルに挿入する方法が示されています。

FUNCTION InsertNewUsers(REF users: LIST OF 
                        STRING):INTEGER IS 
VARIABLES 
  stmt: SQLStatement; 
  retCd: INTEGER; 
ACTIONS 
  (* insert the user names passed in *) 
  retCd := SQLPrepare(stmt,'INSERT INTO USERS
                      VALUES (?)'); 
  IF retCd <= 0 THEN 
    EXIT retCd; 
  END; 
  (* perform the insertions *) 
  FOR users DO 
    retCd := SQLExecute(stmt,users[$current]); 
    IF retCd <= 0 THEN 
      SQLRollback; (* reverse changes and 
                    release locks *) 
      EXIT retCd; 
    END; 
   END; (* for *) 
  (* release the resources used by this Prepared 
   statement *) 
  SQLCloseStatement(stmt); 
END; 

注: TSD Script には同時に準備されるステートメントで制限されるリソースがあるので、 SQLCloseStatement を呼び出して、準備されたステートメントを確実にクローズする必要があります。

パラメーター・マーカーの置き換え

パラメーター・マーカー の置き換えは、準備されたステートメントを使用する処理では不可欠のものです。疑問符 (?) で示されるパラメーター・マーカーは、後で置き換えられる値のプレースホルダーです。

それぞれの値について、疑問符がステートメント文字列に挿入されます (SQLPrepare に提供)。 これらの値のガイドラインは次の通りです。

注: TSD Script では、通常のパラメーター (SQLInsertSQLUpdateSQLSelectInto、および SQLFetch で使用されるもの) によって提供されるものと同等の堅固なタイプの変換を、このパラメーター・マーカーによって提供できません。

ネストされた SQL ステートメント

注: これらのステートメントを適用する先は、Sybase および Microsoft SQLServer だけ です。

一部の DBMS が接続上でサポートするアクティブ SQL ステートメントは、一度に 1 つだけです。たとえば、 SQLFetch ループの本体に SQLSelectInto ステートメントを入れると、2 つの同時 SQL ステートメントが SQLServer とともに必要となります。 Developer's Toolkit は接続を複製することによってこれを補います。複製された接続または "2 次" 接続には、それ自身のトランザクション・スペースがあります。

Developer's Toolkit のトランザクション・モデルによって、すべての接続が同じトランザクションに属しているかのように振る舞うことになります。これは多少正しくない振る舞い (2 フェーズ・コミット・プロトコルを使用しない) ですが、実際には適切に作動します。コミットまたはロールバックでオープン・カーソルおよび準備されたステートメントがクローズされる環境では、外部カーソルがクローズされるまで暗黙的な "自動" コミットを据え置く、という要件がすでにあります。

Developer's Toolkit のこれまでのバージョンでは、ネストされるまたは同時の SQL のすべての操作はトランザクションの内部で実行されていました。これらのバージョンでは、最外部カーソルをオープンする前に SQLBeginWork を呼び出して、この最外部カーソルをクローズする時にコミット (またはロールバック) を実行する必要があります。

このステートメントをそれ自身のトランザクション・スペース内で実行したい場合には、そのステートメントの SQLCommand によって追加の 1 次接続をオープンする必要があります。

Developer's Toolkit 6.0 では、"手動" コミット・モードで同時にステートメントを実行するためのトランザクション・ラッピングはもう不要となります。ただし、DBMS によってカーソルがトランザクションにスパンできない場合に、 "自動" コミット・モードを使用する時にトランザクション・ラッピングがまだ必要となります。

ネストされた SQL ステートメントに関する複雑さおよびそれに付随する問題 (接続オーバーヘッド、異なったトランザクション・スペース内の 2 つの接続から同じテーブルにアクセスする時に起こりうるデッドロックなど) のために、可能なかぎりこれを避けることをお奨めします。

通常、SQL 操作を次の 2 つの部分に分割することができます。

ネストされたステートメントに付随する多くの問題を回避するとともに、この方法には、トランザクション内部で操作の実行が強制されないので、並行性が向上できるという利点があります。ただし、アプリケーションによっては、2 番目の部分のトランザクションが必要となる場合があります。


Tivoli Service Desk 6.0 Developer's Toolkit Script プログラミングの手引き

目次に戻る

著作権