SET
SETコマンドは、データベースに対するアクティビティを実際に行う前にデータベース接続プロパティを設定する場合に使用されます。このコマンドのすべての機能を理解することが非常に重要です。
SET ------------- READONLY -------- *YES ------------------------->
*NO
>-- AUTOCOMMIT ------ *YES ------------------------->
*NO
>-- ISOLATION ------- *NONE ------------------------>
*READCOMMIT
*READUNCOMMITTED
*REPEATABLEREAD
*SERIALIZABLE
>-- PARAMETER ------- *LIST ------------------------>
*SQL
*CALL
*MAP
*NONE
>-- ONERROR --------- *DISCONNECT ------------------>
*CONTINUE
*ROLLBACK
>-- ONWARNING ------- *STOP ------------------------>
*CONTINUE
>-- SQLSTATE -------- *NONE ------------------------|
*ERROR
*WARNING
*ALL
キーワード
READONLY |
このキーワードは、現在のデータベース接続が読み込みアクセスや書き込みアクセスを許可するかどうかを指定します。最初にCONNECTコマンドを使用してデータベース接続を確立する必要があります。このキーワードは、現在のデータベース接続に適用されます。 省略値では、データベース接続が確立されると、読み込みアクセスと書き込みアクセスが許可されます(データベースで課せられている制限によって異なります)。 値が*YESの場合、データベースの変更は各ステートメントの実行後に自動的にコミットされます。 値が*NOの場合、データベースの変更はプログラムによるトランザクションの境界で制御されます。 詳細については、このコマンドの「コメント/警告」を参照してください。 |
AUTOCOMMIT |
このキーワードは、情報がデータベースに自動的にコミットされるかどうかを指定します。このキーワードを使用するには、最初にCONNECTコマンドでデータベース接続を確立する必要があります。このキーワードは、現在のデータベース接続に適用されます。 省略値では、接続が確立されると、自動コミット・モードになります。 値が*YESの場合、データベースの変更は各ステートメントの実行後に自動的にコミットされます。 値が*NOの場合、データベースの変更はプログラムによるトランザクションの境界で制御されます。 詳細については、このコマンドの「コメント/警告」を参照してください。 |
ISOLATION |
このキーワードは、現在のデータベースに適用されるトランザクション・アイソレーションのレベルを指定します。このキーワードを使用するには、CONNECTコマンドでデータベース接続を確立する必要があります。このキーワードは、現在のデータベース接続に適用されます。 省略値は*NONEです。それ以外の場合、 ANSI/ISOのSQL規格で定義されたトランザクションの以下の4つのレベルから選択できます。 *READUNCOMMITTED コミットされていないすべてのデータを接続から読み込むことができます。これは、アイソレーションがない場合(*NONE)と同じではありません。 *READCOMMITTED このレベルでは、ダーティー読み込みは防止されますが、ファントム読み込みやノンリピータブル読み込みは防止されません。このアイソレーション・レベルを使用する場合、現在のトランザクションの開始前にコミットされたデータのみを使用できます。ダーティー・データや、同時トランザクションで行われた変更は使用できません。 このレベルは*READUNCOMMITTEDよりも明らかに制限されます。 *REPEATABLEREAD このレベルでは、ダーティー読み込みやノンリピータブル読み込みは防止されますが、ファントム行は防止されません。つまり、*READUNCOMMITTEDや*READCOMMITTEDと比較した場合、この読み込みを待機しなければならない他のトランザクションが増える可能性があります。 これは*READCOMMITTEDよりも制限されます。 *SERIALIZABLE *SERIALIZABLEでは、トランザクション・アイソレーションが最大になります。トランザクションが*SERIALIZABLEレベルで分離される場合、トランザクションの開始前にコミットされたデータのみを使用できます。ダーティー・データも、トランザクション実行時にコミットされた同時トランザクション変更も使用できません。このレベルでは、トランザクションは同時ではなく次々と効率的に実行されるため、シリアル・トランザクション実行をエミュレートします。 これは*REPEATABLEREADよりも制限されます。 アプリケーションに適用する正しいアイソレーション・レベルを判断するには、これらのアイソレーション・レベルに関して以下の3つの現象を理解する必要があります。 · ダーティー読み込み - トランザクションは、コミットされていないトランザクションで書き込まれたデータを読み込みます。2番目のトランザクションがロールバックされると、ロールバックにより変更が取り消されるため、最初のトランザクションで読み込まれたデータは無効になります。最初のトランザクションは、読み込まれたデータが無効になったことに気付きません。 · ノンリピータブル読み込み - トランザクションは、以前に読み込んだデータを再度読み込み、コミットされた別のトランザクションによってデータが修正されたことを認識します。 · ファントム読み込み - データベースに追加された新しいレコードを、挿入前に開始したトランザクションで検出できる場合、ファントム読み込みが行われます。トランザクションは再度クエリーを実行し、検索条件を満たす行セットを返しますが、コミットされた別のトランザクションによって条件を満たす追加行が挿入されたことを認識します。 ANSI/ISOのSQL規格のアイソレーション・レベルと、対応する動作の概要を以下の「コメント/警告」の表にまとめています。 |
PARAMETER |
このキーワードを使用すると、EXECUTEコマンドやREADコマンドの実行前にSQLステートメントを準備できます。ここで指定した値は、データベースで実行するアクティビティのタイプに大きく依存します。 このキーワードには以下の4つの値が可能です。 · *LIST - EXECUTEコマンドのUPDATEキーワードを使用する場合、この値を設定できます。この方法を使用する場合、データベースに対して追加、更新、または削除する値は、このコマンドのSERVICE_LISTに含まれるリストに指定します。複数のレコードを更新(挿入または削除)する場合、このオプションを使用することをお勧めします(それ以外の場合は、レコードと同じ回数だけEXECUTEを実行する必要がありますが、システムやネットワークに余分な負荷がかかります)。このコマンドの以下の「リストと変数」および「例」を参照してください。 · *SQL - EXECUTEコマンドより前にSQLステートメントを準備する場合、この値を設定できます。SQLステートメントを準備して、このコマンドのSERVICE_LISTで渡される作業リストにSQLステートメントを配置します。この機能は、長いSQLステートメントを使用する場合に特に役立ちます。特に、最大フィールド長がわずか256文字のRDMLアプリケーションの場合に便利です。詳細については、このコマンドの以下の「リストと変数」および「例」を参照してください。 · *CALL - IN、OUT、INOUTの各パラメータを含むプロシージャ・コールを使用する場合、この値を設定できます。 · *MAP - 大きな結果セットがクエリーから返されることが予想される場合、READコマンドを使用して値のリストを受け取るように選択する必要があります。READコマンドを使用するには、このキーワードを*MAPに設定する必要があります。*MAPでは、このコマンドのSERVICE_LISTに列とフィールドのマッピング情報が含まれます。詳細については、このコマンドの以下の「リストと変数」および「例」を参照してください。 · *NONE - 現在のマップ、リスト、SQLステートメントを消去する場合にこの値を使用できます。 |
ONERROR |
このキーワードは、SQLステートメントの実行時に例外が発生した場合に行うアクションを指定する場合に使用されます。 以下の3つのオプションが可能です。 · *ROLLBACK - SQLステートメントの実行時に例外が発生した場合、ロールバックが開始されます。 · *CONTINUE - SQLステートメントの実行時に例外が発生した場合、処理が続行されます。 · *DISCONNECT - SQLステートメントの実行時に例外が発生した場合、データベース接続が閉じられます。 省略値は*DISCONNECTです。 |
ONWARNING |
このキーワードは、SQLステートメントの実行時に警告メッセージが発生した場合に行うアクションの指定に使用されます。 以下の2つの値が可能です。 · *CONTINUE - SQLステートメントの実行時に警告が発生した場合、処理が続行されます。 · *STOP - SQLステートメントの実行時に警告が発生した場合、コマンドが中止します。 省略値は*STOPです。 |
SQLSTATE |
省略値では、SQLExceptionが発生した場合、JSMSTSフィールドはERRORに設定され、SQLWarningが発生した場合、JSMSTSフィールドはWARNINGに設定されます。 このキーワードを使用して、これらの省略値の代わりに実際のSQLxxxxxコードを返すことができます。 以下の4つの値が可能です。 · *ALL - SQLExceptionまたはSQLWarningはSQLxxxxxステータスを返します。 · *ERROR - SQLExceptionはSQLxxxxxステータスを返し、SQLWarningはWARNINGステータスを返します。 · *WARNING ERROR - SQLWarningはSQLxxxxxステータスを返し、SQLExceptionはERRORステータスを返します。 · *NONE - SQLExceptionはERRORステータスを返し、SQLWarningはWARNINGステータスを返します。 省略値は*NONEです。 |
コメント/警告
JDBCドライバーには、コミット制御や例外処理用のベンダー定義の省略値設定があります。例えば、自動コミットは通常有効になっています。
ANSI/ISOのSQL規格のアイソレーション・レベルと、対応する動作の概要を以下の表にまとめています。
アイソレーション・レベル |
ダーティー読み込み |
ノンリピータブル読み込み |
ファントム読み込み |
*READUNCOMMITTED |
可能 |
可能 |
可能 |
*READCOMMITTED |
不可能 |
可能 |
可能 |
*REPEATABLEREAD |
不可能 |
不可能 |
可能 |
*SERIALIZABLE |
不可能 |
不可能 |
不可能 |
SQLService SETコマンドでは、各自の要件に合うようにこれらの設定をオーバーライドする機能が提供されます。
本書では、コミット制御やエラー処理については詳しく説明しません。アイソレーション・レベル、コミット制御、エラー処理に慣れていない場合は、該当トピックについて他の媒体から調べることを強くお勧めします。これらのトピックはかなり一般的であるため、学術書やWebサイトの参照から始めると良いかもしれません。データベース・ベンダーから提供されている、該当トピックに関する資料を確認することもお勧めします。
コミットとロールバックのロジックを広範囲にテストすることを強くお勧めします。
リストと変数
PARAMETERキーワードでは、SQLステートメントを準備する際にかなり役立つ技術が提供されます。この技術を使用すれば、コードは簡素化され、多くの場合、より効率的なアプリケーションを作成できます。
PARAMETERキーワードに値*LIST、*SQL、*MAPまたは*CALLを指定して使用する場合、SETコマンドで作業リストを指定する必要があります。作業リストに含まれる情報は、3つの値のどれを指定するかによって異なります。
以下に、各値の使用目的と、コマンドで渡す必要のあるリスト情報を示します。
*LIST - リモート・データベースから挿入、更新、削除するレコードのリストを渡すことができます。このリストは、プリペアドSQLステートメントとともにリモート・データベースに送られます。プリペアドSQLステートメントはリストのレコードごとに一度実行されます。この機能により、ネットワーク・リソースやシステム・リソースを軽減できます。あるいは、ループ内でSQLステートメントを実行し、更新が必要な個別レコードごとにSQLステートメントをサーバーに送信します。この値で指定された作業リストにより、SQLステートメントで必要な各フィールドの列が1つ提供されます。EXECUTEコマンドで説明するように、列の順序が重要です。
*SQL - EXECUTEコマンドの前にSQLステートメントを準備できます。これは、SQLステートメントが非常に大きい場合に特に役立ちます(例えば、RDMLアプリケーションの最大フィールド・タイプは256文字のため、JSM_COMMANDでこの大きなSQLステートメントを使用する場合、SQLステートメントの挿入に利用可能なスペースはこれよりもかなり少なくなります)。この値を設定する場合、大きなSQLステートメントを作業リストに配置できます。必要に応じて、ステートメントを作業リストの多数の行にわたって配置できます(注:SETコマンドにつき1つのステートメントのみ)。このオプションで渡される作業リストには、SQLステートメントを含む単一文字フィールドを含める必要があります。
*CALL - IN、OUT、INOUTストアド・プロシージャ・コール・パラメータを渡すことができます。作業リストの引数は3列必要です。この3列はそれぞれタイプ、方向、値になります。タイプ列に可能な値は、*CHAR、*VARCHAR、*SMALLINT、*INTEGER、*FLOAT、*DOUBLE、*DECIMALおよび*NUMERICです。方向列に可能な値は*IN、*OUT、*INOUTです。値列は文字列です。
*MAP - データベースのクエリーから大きな結果セットを受け取ることが予想される場合、READコマンドを使用して結果セットの値を取得する必要があります。この方法を使用する場合、列フィールド・マッピングを含む作業リストをこのSETコマンドで渡す必要があります。値*MAPの場合、リストはこの目的で使用されます。渡した作業リストには、列/フィールドのマッピングを記述する2つの列が含まれます。つまり、最初の列には、リモート・テーブルから返される値を保持するためにこの機能で使用されるフィールド名、2番目の列には、リモート・テーブルで名付けられる関連フィールドの名前が保持されます。このリストには、クエリーから返されるフィールドと同じ数の行があります。この機能とその使用場所の詳細については、「READ」コマンドを参照してください。
これらのオプションを互いに組み合わせて使用する可能性も十分にある点に注意してください。この仕組みについて確認するには、以下の例とSQLServiceの例を参照してください。RDMLまたはRDMLXアプリケーションのサービス・コマンドに作業リストを指定する方法については、「SQLServiceの例」を参照してください。
例
SQLServiceサービスのSET、EXECUTE、READの各コマンドは、それぞれ緊密に関連しています。そのため、「SQLServiceの例」の拡張例を確認することをお勧めします。
RDML
* Define the field to hold the JSM command
DEFINE FIELD(#JSMCMD) TYPE(*CHAR) LENGTH(256)
Define the field and list that will hold the SQL command
DEFINE FIELD(#COLCMD) TYPE(*CHAR) LENGTH(100)
DEF_LIST NAME(#WRKCMD) FIELDS(#COLCMD) TYPE(*WORKING)
* SET the commitment control settings
CHANGE FIELD(#JSMCMD) TO('SET ISOLATION(*READCOMMITTED) AUTOCOMMIT(*NO) ONERROR(*ROLLBACK) ONWARNING(*CONTINUE)')
USE BUILTIN(JSM_COMMAND) WITH_ARGS(#JSMCMD) TO_GET(#JSMSTS #JSMMSG)
* Set up the SQL statement in the list then run the SET command
CHANGE FIELD(#COLCMD) TO('SELECT ID,NAME,AGE,SALARY')
ADD_ENTRY TO_LIST(#WRKCMD)
CHANGE FIELD(#COLCMD) TO('FROM TBLNAME')
ADD_ENTRY TO_LIST(#WRKCMD)
CHANGE FIELD(#JSMCMD) TO('SET PARAMETER(*SQL) SERVICE_LIST(COLCMD)')
USE BUILTIN(JSM_COMMAND) WITH_ARGS(#JSMCMD) TO_GET(#JSMSTS #JSMMSG #WRKCMD)
RDMLX
* Define the JSM Command related fields
Define Field(#JSMSTS) Type(*Char) Length(020)
Define Field(#JSMMSG) Type(*Char) Length(256)
Define Field(#JSMCMD) Type(*Char) Length(256)
Define Field(#JSMHND) Type(*Char) Length(4)
* Define the field and the list to hold an SQL statement
Define Field(#COLCMD) Type(*Char) Length(020)
Def_List Name(#WRKCMD) Fields(#COLCMD) Type(*WORKING)
* Set up the commitment control settings
#JSMCMD := 'Set Isolation(*READCOMMITTED) AutoCommit(*NO) OnError(*ROLLBACK) OnWarning(*CONTINUE)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMHND #JSMCMD) To_Get(#JSMSTS #JSMMSG)
* Build an SQL statement then run the Set command
#COLCMD := 'Select ID,NAME,AGE,SALARY'
Add_Entry To_List(#WRKCMD)
#COLCMD := 'From TBLNAME'
Add_Entry To_List(#WRKCMD)
#JSMCMD := 'Set Parameter(*SQL) Service_List(COLCMD)'
Use Builtin(JSMX_COMMAND) With_Args(#JSMHND #JSMCMD) To_Get(#JSMSTS #JSMMSG #MAPLST)