SIGNAL ステートメントは、「返す」エラーの方法です。SIGNAL は、ハンドラー、アプリケーションの外部、またはクライアントにエラー情報を提供します。さらに、エラーの特性(エラーコード、SQLSTATE 値、メッセージ)に対する制御も提供します。
構文とパラメータの説明
SIGNAL がない場合、エラーを返すために他の方法を採用する必要があります。例えば、存在しないテーブルを意図的に参照して、ルーチンがエラーを返すようにします。
SIGNAL ステートメントを実行するには、特別な権限は不要です。
SIGNAL ステートメントの構文は次のとおりです:
SIGNAL 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
}
SIGNAL ステートメントの condition_value は、返すエラー値を示します。これは SQLSTATE 値(5文字の文字列リテラル)または condition_name であり、後者は以前に DECLARE ... CONDITION を使用して定義された名前付き条件を参照します(DECLARE ... CONDITION参照)。
SQLSTATE 値は、エラー、アラート、または「not found」を示すことができます。この値の最初の2文字は、そのエラーのカテゴリを示します。一部のシグナル値はステートメントの終了を引き起こします。詳細については、シグナルがハンドラー、カーソル、およびステートメントに与える影響を参照してください。
SIGNAL ステートメントの SQLSTATE 値は、'00' で始まってはなりません。このような値は成功を示し、エラーシグナルを発行するためには無効です。これは、SIGNAL ステートメントで直接 SQLSTATE 値を指定する場合でも、ステートメント内で参照される名前付き条件で SQLSTATE 値を指定する場合でも同様です。この値が無効である場合、Bad SQLSTATE エラーが発生します。
一般的な SQLSTATE 値のシグナルを発行するには、「45000」を使用します。これは「unhandled user-defined exception」という意味です。
SIGNAL ステートメントには、オプションで SET 句を含めることができます。この句には複数のシグナル項目を含めることができ、condition_information_item_name = simple_value_specification リスト内でカンマで区切られます。
各 condition_information_item_name は、SET 句で一度しか指定できません。そうしないと、Duplicate condition information item エラーが発生します。
有効な simple_value_specification 指示子として、ストアドプロシージャまたは関数のパラメータ、DECLARE で宣言されたストアドプロシージャのローカル変数、ユーザー定義変数、システム変数、またはリテラルを使用できます。
condition_information_item_name 値の詳細については、シグナル条件情報項目を参照してください。
次の例では、ストアドプロシージャ proc は、入力パラメータである pval の値に基づいて、エラーまたはアラートシグナルを発行します。
CREATE PROCEDURE proc(pval INT)
BEGIN
DECLARE psign CONDITION FOR SQLSTATE '45000';
IF pval = 0 THEN
SIGNAL SQLSTATE '01000';
ELSEIF pval = 1 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred';
ELSEIF pval = 2 THEN
SIGNAL psign
SET MESSAGE_TEXT = 'An error occurred';
ELSE
SIGNAL SQLSTATE '01000'
SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1001;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1002;
END IF;
END;
pval が0の場合、proc() はアラートシグナルを発行します。これは、'01' で始まる SQLSTATE 値がアラートカテゴリのシグナルだからです。このアラートはプロセスを終了させず、プロセスが終了した後に SHOW WARNINGS で確認できます。
pval が1の場合、proc() はエラーシグナルを発行し、MESSAGE_TEXT 条件情報項目を設定します。エラーはプロセスを終了させ、エラー情報を含むテキストを返します。
pval が2の場合、同じエラーシグナルが発行されますが、この場合 SQLSTATE 値は名前付き条件を使用して指定されます。
pval が他の任意の値の場合、proc() は最初に警告シグナルを発行し、メッセージテキストとエラー番号の条件情報項目を設定します。このアラートはプロセスを終了させないため、実行は続行され、その後 proc() はエラーシグナルを発行します。このエラーはプロセスを終了させます。アラートで設定されたメッセージテキストとエラー番号は、エラー情報とともに返される値に置き換えられます。
SIGNAL は通常ストアドプロシージャで使用されますが、拡張機能として、ハンドラーコンテキスト外で使用することもできます。例えば、mysql クライアントプログラムを呼び出すとき、プロンプトに次のステートメントを入力できます。
SIGNAL SQLSTATE '66666';
CREATE TRIGGER trg BEFORE INSERT ON tbl
FOR EACH ROW SIGNAL SQLSTATE '66666';
SIGNALの実行ルール
SIGNAL の実行ルールは以下のとおりです:
SIGNALステートメントが特定のSQLSTATE値を指示する場合、その値は指定された条件を示すために使用されます。例:CREATE PROCEDURE proc(divisor INT) BEGIN IF divisor = 0 THEN SIGNAL SQLSTATE '22012'; END IF; END;SIGNALステートメントで名前付けられた条件を使用する場合、その条件はSIGNALステートメントに適用される範囲内で宣言されていなければならず、条件を定義するにはエラーコードではなくSQLSTATE値を使用する必要があります。指定された条件がSIGNALステートメントの範囲内に存在しない場合、「Undefined CONDITION」というエラーが発生します。例:CREATE PROCEDURE proc(divisor INT) BEGIN DECLARE div_by_zero CONDITION FOR SQLSTATE '22012'; IF divisor = 0 THEN SIGNAL div_by_zero; END IF; END;SIGNALがSQLSTATE値ではなくエラーコードを使用して定義された名前付けられた条件を参照する場合、「SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE」というエラーが報告されます。次のステートメントは、名前付けられた条件がエラーコードに関連付けられているため、このエラーを引き起こします。DECLARE no_table_found CONDITION FOR 1051; SIGNAL no_table_found;指定された名前の条件が異なる範囲で複数回宣言されている場合、ローカル範囲の宣言が適用されます。
以下の例では、
divisorが0の場合、最初のSIGNALステートメントが実行されます。一番内側のone_error条件宣言が適用され、SQLSTATE '22012'が発生します。divisorが0でない場合、2番目のSIGNALステートメントが実行されます。一番外側のone_error条件宣言が適用され、SQLSTATE '45000'が発生します。CREATE PROCEDURE proc(divisor INT) BEGIN DECLARE one_error CONDITION FOR SQLSTATE '45000'; IF divisor = 0 THEN BEGIN DECLARE one_error CONDITION FOR SQLSTATE '22012'; SIGNAL one_error; END; END IF; SIGNAL one_error; END;例外ハンドラー内でシグナルを発生させることができます。以下の例では、
CALL proc()がDROP TABLEステートメントを取得します。no_table_foundという名前のテーブルが存在しないため、例外ハンドラーが有効になります。例外ハンドラーは元のエラー(「no such table」)を破棄し、SQLSTATE '99999'とAn error occurredを使用してエラーを表示します。CREATE PROCEDURE proc() BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN SIGNAL SQLSTATE VALUE '99999' SET MESSAGE_TEXT = 'An error occurred'; END; DROP TABLE no_table_found; END;
シグナル条件情報項目
標準SQLについて、以下の表はSIGNAL(またはRESIGNAL)ステートメントで設定できる診断領域条件情報項目の名前を示しています。ここでMYSQL_ERRNOは拡張項目です。
| 情報項目名 | データ型 |
|---|---|
| MESSAGE_TEXT | VARCHAR(64) |
| MYSQL_ERRNO | SMALLINT UNSIGNED |
文字項目の文字セットはUTF-8です。条件情報項目ではNULLをSIGNALステートメントに割り当てることはできません。
SIGNALステートメントは常に、SQLSTATE値が定義する条件を直接または間接的に参照してSQLSTATE値を指定します。SQLSTATE値の最初の2文字はそのカテゴリーであり、カテゴリーによって条件情報項目のデフォルト値が決定されます。詳細は以下の表を参照してください。
| SQLSTATE値のカテゴリ | 説明 |
|---|---|
Class = '00' (success) |
無効です。'00'で始まるSQLSTATE値は成功を示し、SIGNALに対して無効です。 |
Class = '01' (warning) |
MESSAGE_TEXT='Unhandled user-defined warning condition'; MYSQL_ERRNO=ER_SIGNAL_WARN |
Class = '02' (not found) |
MESSAGE_TEXT='Unhandled user-defined not found condition'; MYSQL_ERRNO=ER_SIGNAL_NOT_FOUND |
Class > '02' (exception) |
MESSAGE_TEXT='Unhandled user-defined exception condition'; MYSQL_ERRNO=ER_SIGNAL_EXCEPTION |
SIGNAL実行後に取得されるエラー値は、SIGNALステートメントとMESSAGE_TEXTおよびMYSQL_ERRNO項目によって引き起こされるSQLSTATE値です。これらの値は、以下のC APIから取得できます。
mysql_sqlstate()はSQLSTATE値を返します。mysql_errno()はMYSQL_ERRNO値を返します。mysql_error()はMESSAGE_TEXT値を返します。
SQLレベルでは、SHOW WARNINGSおよびSHOW ERRORS出力のCodeおよびMessage列はMYSQL_ERRNOおよびMESSAGE_TEXTの値を示します。
診断領域から情報を取得するには、GET DIAGNOSTICSステートメントを使用してください。詳細については、GET DIAGNOSTICSを参照してください。
シグナルがハンドラー、カーソル、およびステートメントに与える影響
シグナルの種類はステートメントの実行に異なる影響を与えます。以下の表に示されています。カテゴリはエラーの深刻さを決定するために使用されます。SIGNAL の目的は、ユーザー生成のエラーを明示的に発生させることであるため、シグナルは決して無視されることはありません。特に厳密モードでは、sql_mode システム変数の値は無視されます。
| SQLSTATE値のカテゴリー | 説明 |
|---|---|
Class = '00' (success) |
無効です。'00'で始まるSQLSTATE値は成功を示し、SIGNALに対して無効です。 |
Class = '01' (warning) |
SHOW WARNINGSはシグナルを表示します。SQLWARNINGハンドラーがシグナルをキャッチします。関数の返却を引き起こすRETURNステートメントは診断領域をクリアするため、ストレージ関数から警告を返すことはできません。このステートメントは存在する可能性のある警告をすべてクリアし(warning_countを0にリセット)、警告を再表示します。 |
Class = '02' (not found) |
NOT FOUNDハンドラーがシグナルをキャッチします。カーソルには影響しません。シグナルがストレージ関数内で処理されない場合(つまり、DECLARE ... HANDLERを使用して発行されたSQLSTATE値のハンドラーを定義していない場合)、ステートメントは終了します。 |
Class > '02' (exception) |
SQLEXCEPTIONハンドラーがシグナルをキャッチします。シグナルがストレージ関数内で処理されない場合(つまり、DECLARE ... HANDLERを使用して発行されたSQLSTATE値のハンドラーを定義していない場合)、ステートメントは終了します。 |
Class = '40' |
普通の例外と見なされます。 |