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' |
+-------+------+----------------------------------+