複合 SQL を利用すると、複数のステートメントを実行可能な 1 つのブロックとしてグループ化することができます。このステートメントのブロックを入力パラメーター値と共に使って、 1 つの連続ストリームで実行することができ、これにより実行時間およびネットワーク通信量を少なくすることができます。複合 SQL は、INSERT、UPDATE、および DELETE ステートメントの集まりを効果的に実行するのに頻繁に使用されます。
動的に作成される SQL ステートメント (照会ステートメントを除く) は、いずれも複合ステートメントの内部にあるステートメントとして実行することができます。複合 SQL ステートメントの中にあるステートメントは、サブステートメントと呼ばれます。複合 SQL は、サブステートメントが実行される順序を保証しないので、ステートメント間に依存性があってはなりません。
複合 SQL ステートメントはネストすることはできません。複合 SQL ステートメントの許可 ID は、複合 SQL ステートメント内に含まれる個々のサブステートメントのすべてについて適切な許可でなければなりません。
複合 SQL がサポートされるのは、DB2 ユニバーサル・データベースに接続する場合、または DB2 コネクト V 2.3 以降の DRDA 環境にある場合です。
複合 SQL ステートメントのブロックを指定する場合は、 BEGIN COMPOUND ステートメントと END COMPOUND ステートメントでサブステートメントを囲みます。 BEGIN COMPOUND 構文を次に示します。
>>-BEGIN COMPOUND--+-ATOMIC-----+---STATIC--+----------------------------------+-> '-NOT ATOMIC-' '-STOP AFTER FIRST--?--STATEMENTS--' >--------------------------------------------------------------><
END COMPOUND 構文を次に示します。
>>-END COMPOUND---+--------+----------------------------------->< '-COMMIT-'
COMMIT オプションを指定すると、すべてのサブステートメントが正常に実行された場合に、それらがコミットされます。 COMMIT は、複合ステートメントの前にあるステートメントも含めて、現行のトランザクションに適用されます。 COMMIT が指定されており、かつ接続が調整分散接続 (SQL_COORDINATED_TRANS) である場合には、エラーが返されます (SQLSTATE 25000)。
END COMPOUND の後に COMMIT オプションを指定しないと、アプリケーションが自動コミット・モードで操作を行っている場合を除いて、サブステートメントはコミットされません。自動コミット・モードで操作されている場合は、END COMPOUND 時にコミットが出されます。自動コミット・モードの詳細については、コミットまたはロールバックを参照してください。
図 15 は、複合 SQL ステートメントを実行する上で必要な関数呼び出しの一般的な順序を示しています。次の点について注意してください。
![]() |
複合ステートメントが ATOMIC で、 END COMPOUND SQLExecDirect() 呼び出しが次のものを返すと、次のようになります。
SQLCA 内の情報のほとんどは、データベース・サーバーが最後のサブステートメントを処理したときに設定した値を反映しています。たとえば、SQLCODE および SQLSTATE などです。 1 つまたは複数のエラーが発生し、いずれも重大でなければ、 SQLCA の SQLERRMC フィールドには、これらのエラーのうち最大 7 つに関する情報が入っています。
複合ステートメントが NOT ATOMIC で、 END COMPOUND SQLExecDirect() 呼び出しが次のものを返すと、以下のようになります。
注: | 複合 SQL 実行後の SQLCA の内容に関する詳細は、SQL 解説書 を参照してください。 |
次の例では、新規の AWARDS 表に行を挿入するために、 4 つのサブステートメントからなる複合ステートメントを実行します。
/* ... */ SQLCHAR * stmt[] = { "INSERT INTO awards (id, award) " "SELECT id, 'Sales Merit' from staff " "WHERE job = 'Sales' AND (comm/100 > years)", "INSERT INTO awards (id, award) " "SELECT id, 'Clerk Merit' from staff " "WHERE job = 'Clerk' AND (comm/50 > years)", "INSERT INTO awards (id, award) " "SELECT id, 'Best ' concat job FROM STAFF " "WHERE comm = (SELECT max(comm) FROM staff WHERE job = 'Clerk')", "INSERT INTO awards (id, award) " "SELECT id, 'Best ' concat job FROM STAFF " "WHERE comm = (SELECT max(comm) FROM STAFF WHERE job = 'Sales')", } ; SQLINTEGER i ; /* ... */ /* Prepare 4 substatements */ for ( i = 1; i < 4; i++ ) { rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &cmhstmt[i] ) ; CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ; rc = SQLPrepare( cmhstmt[i], stmt[i], SQL_NTS ) ; CHECK_HANDLE( SQL_HANDLE_STMT, cmhstmt[i], rc ) ; } rc = SQLExecDirect( hstmt, ( SQLCHAR * ) "BEGIN COMPOUND NOT ATOMIC STATIC", SQL_NTS ) ; CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ; /* Execute 4 substatements */ for ( i = 1; i < 4; i++ ) { rc = SQLExecute( cmhstmt[i] ) ; CHECK_HANDLE( SQL_HANDLE_STMT, cmhstmt[i], rc ) ; } /* Execute the COMPOUND statement (of 4 sub-statements) */ printf( "Executing the COMPOUND statement (of 4 sub-statements)\n" ) ; rc = SQLExecDirect( hstmt, ( SQLCHAR * ) "END COMPOUND COMMIT", SQL_NTS ) ; CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ; rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ; for ( i = 1; i < 4; i++ ) { rc = SQLFreeHandle( SQL_HANDLE_STMT, cmhstmt[i] ) ; CHECK_HANDLE( SQL_HANDLE_STMT, cmhstmt[i], rc ) ; }