RESIGNAL ステートメントは、ストアドプロシージャや関数、トリガー、またはイベント内の複合ステートメントで条件処理プログラムを実行する際に利用可能なエラー条件情報を渡すために使用されます。
RESIGNALの構文とパラメータの説明
RESIGNAL は、エラー条件情報を伝達する前に、一部または全部の情報を変更する場合があります。RESIGNAL は SIGNAL と関連しており、SIGNAL は条件を発信できますが、RESIGNAL は既存のエラー情報に基づいて対応する変更を行うことしかできません。
RESIGNAL ステートメントを実行するためには、特別な権限は必要ありません。
RESIGNAL ステートメントの構文は以下のとおりです:
RESIGNAL [condition_value]
[SET signal_information_item
[, signal_information_item] ...]
condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
}
signal_information_item:
condition_information_item_name = simple_value_specification
condition_information_item_name: {
MESSAGE_TEXT
| MYSQL_ERRNO
}
condition_value と signal_information_item については、RESIGNAL の定義とルールは SIGNAL と同じです。例えば、condition_value は SQLSTATE 値である可能性があり、この値はエラー、警告、または「not found」を示すことができます。詳細については、SIGNALを参照してください。
RESIGNAL 構文内の condition_value と SET 句はどちらもオプションです。使用方法は以下のとおりです:
単独の
RESIGNALRESIGNAL;新しいシグナル情報を含む
RESIGNAL:RESIGNAL SET signal_information_item [, signal_information_item] ...;条件値と新しいシグナル情報を含む
RESIGNAL:RESIGNAL condition_value [SET signal_information_item [, signal_information_item] ...];
これらの使用方法はすべて、診断領域と条件領域に以下の変更をもたらします:
1つの診断領域には、1つ以上の条件領域が含まれます。
条件領域には、
SQLSTATE値やMESSAGE_TEXTなどの条件情報項目が含まれます。
スタックの診断領域については、ハンドラが制御権を取得すると、診断領域をスタックのトップにプッシュします。そのため、ハンドラの実行中は2つの診断領域が存在します:
最初の(現在の)診断領域は、最後の診断領域のコピーとして開始され、ハンドラが現在の診断領域の最初のステートメントで上書きします。
最後の(スタック上の)診断領域には、ハンドラが制御を開始する前に設定された条件領域が含まれます。
説明
診断領域内の条件領域の最大数は、
max_error_countシステム変数の値によって決定されます。
すべての形式の RESIGNAL では、現在のコンテキストが条件ハンドラである必要があります。そうでない場合、RESIGNAL は無効であり、ハンドラが非アクティブな状態でエラーが発生します。例:
obclient> CREATE PROCEDURE p1() RESIGNAL;
Query OK, 0 rows affected
obclient> CALL p1();
ERROR 1645 (0K000): RESIGNAL when handler not active
単独のRESIGNAL
単純な RESIGNAL の意味は「何も変更せずにエラーを伝える」ことです。RESIGNAL のみを使用することで、前の診断領域を復元し、現在の診断領域とすることができます。つまり、診断領域のスタックを「ポップアップ」表示します。
例:
DROP TABLE IF EXISTS tbl1;
delimiter //
CREATE PROCEDURE proc()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET @err_count = @err_count + 1;
IF @x = 0 THEN RESIGNAL; END IF;
END;
DROP TABLE tbl1;
END//
delimiter ;
SET @err_count = 0;
SET @x = 0;
CALL proc();
DROP TABLE tbl1 ステートメントの実行が失敗したと仮定します。診断領域のスタックは以下のようになります:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
その後、EXIT ハンドラーに入る処理を実行します。まず、診断領域をスタックのトップにプッシュします。以下のようになります:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
DA 2. ERROR 1051 (42S02): Unknown table 'tbl1'
この時点で、第一(現在)および第二(スタック)の診断領域の内容は同じです。その後、ハンドラー内で実行されるステートメントによって、第一の診断領域を変更することができます。
通常、プロシージャーステートメントは最初の診断領域をクリアします(BEGIN は除く)。SET ステートメントは、クリア、操作の実行、および「成功」という結果の生成を行うことができます。現在の診断領域のスタックは以下のようになります:
DA 1. ERROR 0000 (00000): Successful operation
DA 2. ERROR 1051 (42S02): Unknown table 'tbl1'
この時点で、@x = 0 の場合、RESIGNAL は診断領域のスタックをポップアップ表示し、現在の診断領域は以下のようになります:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
@x が0でない場合、ハンドラーは終了します。これは、現在の診断領域にはこれ以上の用途がない(すでに「処理済み」であるため)ことを意味し、それを破棄してスタック上の次の診断領域を現在の診断領域とすることができます。現在の診断領域のスタックは以下のようになります:
DA 1. ERROR 0000 (00000): Successful operation
上記の例は、ハンドラーの実行が、ハンドラーを有効化した条件に関する情報を破壊しないことを示しています。
新しいシグナル情報を持つRESIGNAL
SET 句を持つ RESIGNAL は新しいシグナル情報を提供するため、このステートメントの意味は「エラーを変更して渡す」となります。構文は次のとおりです:
RESIGNAL SET signal_information_item [, signal_information_item] ...;
単独の RESIGNAL と同様に、診断領域のスタックをポップアップ表示することで、元の情報が消えます。単独の RESIGNAL と異なり、SET 句で指定された内容はすべて変更されます。
例:
DROP TABLE IF EXISTS tbl1;
delimiter //
CREATE PROCEDURE proc()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET @err_count = @err_count + 1;
IF @x = 0 THEN RESIGNAL SET MYSQL_ERRNO = 5; END IF;
END;
DROP TABLE tbl1;
END//
delimiter ;
SET @err_count = 0;
SET @x = 0;
CALL proc();
DROP TABLE tbl1 ステートメントが失敗したと仮定します。診断領域のスタックは次のとおりです:
DA 1. ERROR 1051 (42S02): Unknown table 'tbl1'
一方、RESIGNAL SET MYSQL_ERRNO = 5 ステートメントはスタックを生成し、エラー番号を変更します。次のとおりです。
DA 1. ERROR 5 (42S02): Unknown table 'tbl1'
RESIGNAL ステートメントは任意またはすべてのシグナル情報項目を変更でき、診断領域の最初の条件領域のスタイルを変更します。
条件値とオプションの新しい信号情報を持つRESIGNAL
条件値を持つ RESIGNAL は「条件を現在の診断領域にプッシュする」という意味です。SET 句が存在する場合、エラーメッセージも変更されます。
RESIGNAL condition_value
[SET signal_information_item [, signal_information_item] ...];
この形式の RESIGNAL は、前の診断領域を復元して現在の診断領域にします。つまり、診断領域スタックを「ポップアップ」表示させる点では、単独の RESIGNAL と同じです。ただし、条件値または信号情報に基づいて診断領域を変更します。
例:
DROP TABLE IF EXISTS tbl1;
delimiter //
CREATE PROCEDURE proc()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET @err_count = @err_count + 1;
IF @x = 0 THEN RESIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=5; END IF;
END;
DROP TABLE tbl1;
END//
delimiter ;
SET @err_count = 0;
SET @x = 0;
CALL proc();
SHOW ERRORS;
例では、RESIGNAL が発生した場合、現在の条件領域は前の例とは異なります。条件値を使用しているため、既存の条件を置き換えるのではなく、条件が追加されます。
RESIGNAL ステートメントには条件値(SQLSTATE '45000')が含まれているため、新しい条件領域が追加され、診断領域のスタックは次のようになります:
DA 1. (condition 2) ERROR 1051 (42S02): Unknown table 'tbl1'
(condition 1) ERROR 5 (45000) Unknown table 'tbl1'
この例の CALL proc() と SHOW ERRORS の結果は次のとおりです:
mysql> CALL proc();
ERROR 5 (45000): Unknown table 'xx'
mysql> SHOW ERRORS;
+-------+------+----------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------+
| Error | 1051 | Unknown table 'xx' |
| Error | 5 | Unknown table 'xx' |
+-------+------+----------------------------------+