DECLARE HANDLER ステートメント

DECLARE HANDLER ステートメントは、例外を処理するエラー・ハンドラーを作成します。

構文

構文図を読むビジュアル構文図をスキップDECLARECONTINUEEXITハンドラー対象状態stmt
STATE
構文図を読むビジュアル構文図をスキップ<<-- , --<<SQLSTATE「 テキスト 'LIKE「 テキスト 'ESCAPE「 テキスト '

明示的に宣言されている両方ハンドラーを宣言できます (BEGIN...END) スコープと暗黙的に宣言された有効範囲 (例えば、IF ステートメントの ELSE 節)。 しかし、すべてのハンドラー宣言を、有効範囲の先頭つまり他のステートメントの前に一緒に置かなければなりません。

例外がない場合は、ハンドラーがあっても SQL プログラムの動作やパフォーマンスには影響しません。 例外が発生した場合、 IBM® Integration Bus は、例外がノードを離れるか (ハンドラーが存在しない場合と同様に)、または一致するハンドラーが見つかるまで、例外の SQL 状態と関連するすべてのハンドラーに関連する SQL 状態を比較します。 ハンドラーは、1 つの有効範囲内で、宣言されている順序で最初のハンドラーから最後のハンドラーに向かって検索されます。 有効範囲は最内部から最外部に向かって検索されます。

DECLARE...で指定された SQL 状態値 ハンドラー ... ステートメントは、例外の SQL 状態と直接比較することも、ワイルドカード文字を使用して比較することもできます。 状態値を直接比較するには、VALUE を指定するか、または条件演算子を指定しません。 ワイルドカード比較を行うには、下線文字を使用して 1 文字ワイルドカードを表すかパーセント文字を使用して複数文字ワイルドカードを表し、LIKE 演算子を指定します。 ワイルドカードの方式を使用すると、漏れなくリストしなくても、一般的なタイプの例外をすべて処理できます。

一致しているハンドラーが検出されると、SQLSTATE およびその他の特殊レジスターが (このセクションで後ほど取り上げられている規則に従って) 更新され、ハンドラーのステートメントが処理されます。

ハンドラーのステートメントは、単一のステートメントである必要があるため、通常は複合ステートメント です(BEGIN...END) 複数のステートメントが含まれています。 これらの内部ステートメントに関連した特殊な動作はないので、特別な制約事項はありません。 例えば、RETURN、ITERATE、または LEAVE を組み込むことができます。この場合、有効範囲自体に含まれている場合と同様の影響を、含まれているルーチンやループ構成体に及ぼします。

ハンドラーには、そのハンドラー自体の内部で起きる例外のハンドラーを含めることができます。

ハンドラーのコードの処理が、追加の未処理の例外をスローせずに完了すると、正常なコードの実行が以下のように再開されます。
  • EXIT ハンドラーの場合、ハンドラーの有効範囲の後の最初のステートメントが、次に処理されます。
  • CONTINUE ハンドラーの場合、例外を生成したステートメントの後の直接含まれる最初のステートメントになります。

個々のハンドラーには、それぞれの SQLCODE、SQLSTATE、SQLNATIVEERROR、および SQLERRORTEXT 特殊レジスターがあります。 これらは有効範囲入り、その値はハンドラーの最初のステートメントが実行される直前に設定されます。 これらの値は、ハンドラーの最後のステートメントが実行されるまで有効です。 SQLSTATE 値はハンドラー間で持ち越されないので、ハンドラーは個別に作成できます。

ハンドラーが例外を吸収し、例外は入力ノードに達しないので、トランザクションはロールバックされずにコミットされます。 このようにならないようにするには、ハンドラーで RESIGNAL ステートメントか THROW ステートメントを使用できます。

HANDLER で使用できる有効な SQLSTATES のリストについては、 SQLSTATE 関数 を参照してください。

例 1

以下の例は、USER EXCEPTION を適切に使用して、SQLCODE、SQLSTATE、SQLNATIVEERROR、および SQLERRORTEXT を例外からハンドラーに渡す方法を示しています。 また、この例では SQLSTATE を使って特定の例外をキャッチします。
DECLARE retryCount INTEGER 0;
DECLARE afterCount INTEGER 0;

WHILE retryCount <= 10 DO
  DECLARE EXIT HANDLER FOR SQLSTATE VALUE 'U11222'
  BEGIN	
    /* This demonstrates how to pass data to the HANDLER in the SQL 
       special registers */
    SET OutputRoot.XMLNSC.Top.WHILE.mySQLCODE = SQLCODE;
    SET OutputRoot.XMLNSC.Top.WHILE.mySQLSTATE = SQLSTATE;
    SET OutputRoot.XMLNSC.Top.WHILE.mySQLNATIVEERROR = SQLNATIVEERROR;
    SET OutputRoot.XMLNSC.Top.WHILE.mySQLERRORTEXT = SQLERRORTEXT;

    SET retryCount = retryCount + 1;

    /* If we are an EXIT HANDLER, control is now passed to back to the 
       WHILE statement */
  END;

  /* In a real scenario this could be a PROPAGATE statement, and the exception
     could be thrown by a 'downstream' node. In this case the HANDLER would 
     normally cope with a wider range of exception, for example, using LIKE '%' */
  THROW USER EXCEPTION VALUES( -1, 'U11222', 42, 'error text' );
          
  /* This is the next statement executed if it is a CONTINUE HANDLER */
  SET afterCount = afterCount + 1;
          
END WHILE;
        
SET OutputRoot.XMLNSC.Top.WHILE.retryCount = retryCount;
SET OutputRoot.XMLNSC.Top.WHILE.afterCount = afterCount;   

With EXIT (as above) the output is:
<Top>
  <WHILE>
    <mySQLCODE>-1</mySQLCODE>
    <mySQLSTATE>U11222</mySQLSTATE>
    <mySQLNATIVEERROR>42</mySQLNATIVEERROR>
    <mySQLERRORTEXT>error text</mySQLERRORTEXT>
    <retryCount>11</retryCOUNT>
    <afterCount>0</afterCOUNT>
  </WHILE>
</Top>

Changing the HANDLER to be CONTINUE (DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE
'U11222') then the output is:
<Top>
  <WHILE>
    <mySQLCODE>-1</mySQLCODE>
    <mySQLSTATE>U11222</mySQLSTATE>
    <mySQLNATIVEERROR>42</mySQLNATIVEERROR>
    <mySQLERRORTEXT>error text</mySQLERRORTEXT>
    <retryCount>11</retryCOUNT>
    <afterCount>11</afterCOUNT>
  </WHILE>
</Top>
次のように違いがあります。afterCount出力メッセージに表示されます。

例 2

-- Drop the tables so that they can be re-created with the latest definition.
-- If the program has never been run before, errors will occur because you
-- can't drop tables that don't exist. We ignore these.
  BEGIN
    DECLARE CONTINUE HANDLER FOR SQLSTATE LIKE'%' BEGIN END;

    PASSTHRU 'DROP TABLE Shop.Customers' TO Database.DSN1;
    PASSTHRU 'DROP TABLE Shop.Invoices'  TO Database.DSN1;
    PASSTHRU 'DROP TABLE Shop.Sales'     TO Database.DSN1;
    PASSTHRU 'DROP TABLE Shop.Parts'     TO Database.DSN1;
  END;