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文字の文字列リテラル)または、DECLARE ... CONDITION で事前に定義された名前付き条件を参照する condition_name のいずれかです([DECLARE ... CONDITION](../900.pl-exception-handling-statement-mysql/200.declare-condition-mysql.md を参照)。
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 句内で1回だけ指定できます。そうでない場合、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です。条件情報項目には、SIGNAL ステートメントに NULL を代入することはできません。
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' |
普通の例外と見なされます。 |