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 を参照してください)。
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です。条件情報項目に 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' |
普通の例外と見なされます。 |