SQL文は診断領域の診断情報を生成できます。標準SQLには、各ネストされた実行コンテキストの診断領域を含むスタックがあります。標準SQLはまた、GET STACKED DIAGNOSTICS構文をサポートしており、条件処理プログラムの実行中に2番目の診断領域を参照するために使用されます。本記事では主に、診断領域の構造、識別される情報項目、診断領域のクリアと設定、および診断領域のスタックへの投入とスタックからの取り出し方について説明します。
診断領域の構造
診断領域には、以下の2種類の情報が含まれます:
ステートメント情報。例えば、発生した条件の数や影響を受けた行数などです。
条件情報。例えば、エラーコードやメッセージなどです。1つのステートメントが複数の条件を引き起こした場合、診断領域のこの部分では、各条件ごとに条件領域が設けられます。ステートメントがいずれの条件も引き起こさなかった場合、診断領域のこの部分は空になります。
以下の例は、3つの条件を引き起こすステートメントについて、診断領域に含まれるステートメント情報と条件情報を示しています。
Statement information: -- ステートメント情報
row count
... other statement information items ... -- その他のステートメント情報項目
Condition area list: -- 条件領域リスト
Condition area 1: -- 条件領域 1
error code for condition 1 -- 条件 1 のエラーコード
error message for condition 1 -- 条件 1 のエラーメッセージ
... other condition information items ... -- その他の条件情報項目
Condition area 2: -- 条件領域 2
error code for condition 2: -- 条件 2 のエラーコード
error message for condition 2 -- 条件 2 のエラーメッセージ
... other condition information items ... -- その他の条件情報項目
Condition area 3: -- 条件領域 3
error code for condition 3 -- 条件 3 のエラーコード
error message for condition 3 -- 条件 3 のエラーメッセージ
... other condition information items ... -- その他の条件情報項目
診断領域の情報項目
診断領域には、ステートメント情報と条件情報の項目が含まれます。数値項目は整数であり、文字項目の文字セットはUTF-8です。どの項目もNULLを取ることはできません。診断領域を埋めるステートメントでステートメント情報または条件情報の項目が設定されていない場合、その値はデータ型に応じて0または空文字列になります。
診断領域には、以下のステートメント情報が含まれます:
NUMBER:情報のある条件領域の数を示す整数。ROW_COUNT:ステートメントの影響を受けた行数を示す整数。ROW_COUNTはROW_COUNT()関数と同じ値を持ちます。
診断領域の条件情報部分には、各条件の条件領域が含まれます。条件領域は、1からステートメントの条件NUMBER項目の値までの番号で番号付けされます。NUMBERが0の場合、条件領域はありません。
標準SQLでは、各条件領域には以下のリストの項目が含まれます(MYSQL_ERRNOは拡張項目です):
RETURNED_SQLSTATE:条件を示すSQLSTATE値の文字列。MESSAGE_TEXT:条件のエラーメッセージを示す文字列。MYSQL_ERRNO:条件のエラーコードを示す整数。
上記の定義は、シグナル(SIGNALまたはRESIGNALステートメント)によって生成されない条件に適用されます。
SIGNAL(またはRESIGNAL)ステートメントが診断領域を埋める場合、そのSET句はRETURNED_SQLSTATEを除く任意の条件情報項目にデータ型の有効な値を割り当てることができます。SIGNALはまた、RETURNED_SQLSTATEの値を設定します。この値はSIGNALステートメントのSQLSTATEパラメータから取得され、SET句で直接設定されるわけではありません。
SIGNALはまた、ステートメント情報項目NUMBERを1に設定し、ROW_COUNTを-1に設定してエラーを示します。それ以外の場合は0に設定します。
診断領域のクリアと埋め込み
非診断SQL文は自動的に診断領域を埋め込み、SIGNAL および RESIGNAL 文を使用して診断領域の内容を明示的に設定できます。GET DIAGNOSTICS を使用して診断領域を確認し、指定した情報を抽出するか、SHOW WARNINGS または SHOW ERRORS を使用して警告やエラーを確認できます。
SQL文が診断領域をクリアし、設定する方法は以下のとおりです:
サーバーが文の解析後に実行を開始すると、診断領域内の非診断文をクリアします。診断文は診断領域をクリアしません。以下の文は診断文に該当します:
GET DIAGNOSTICSSHOW ERRORSSHOW WARNINGS
文が条件を発生させた場合、診断領域はそれより前の文の条件をクリアします。ただし、
GET DIAGNOSTICSとRESIGNALによって発生させられた条件は、診断領域に追加され、クリアされません。
したがって、診断領域の文は、実行開始時にクリアされなくても、文が条件を発生させた場合にはクリアされます。
以下の例は、さまざまな文が診断領域に与える影響を示し、SHOW WARNINGS を使用して格納された条件情報を表示しています。
例1:DROP TABLE 文は診断領域をクリアし、条件が発生した場合に診断領域を埋め込みます。
obclient> DROP TABLE IF EXISTS test.no_table_found;
Query OK, 0 rows affected, 1 warning
obclient> SHOW WARNINGS;
+-------+------+-------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------+
| Note | 1051 | Unknown table 'test.no_table_found' |
+-------+------+-------------------------------------+
1 row in set
例2:SET 文はエラーを生成するため、診断領域をクリアしてから埋め込みます。
obclient> SET @var1 = @@var;
ERROR 1193 (HY000): Unknown system variable 'var'
obclient> SHOW WARNINGS;
+-------+------+-------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------+
| Error | 1193 | Unknown system variable 'var' |
+-------+------+-------------------------------+
1 row in set
例3:前述の例で SET 文が条件を生成したため、この時点で GET DIAGNOSTICS の有効な条件番号は1のみです。以下の文は警告を生成し、条件番号2を使用します。この警告は診断領域に追加され、クリアされません。
obclient> GET DIAGNOSTICS CONDITION 2 @var2 = MESSAGE_TEXT;
Query OK, 0 rows affected, 1 warning
obclient> SHOW WARNINGS;
+-------+------+------------------------------+
| Level | Code | Message |
+-------+------+------------------------------+
| Error | 1193 | Unknown system variable 'var'|
| Error | 1753 | Invalid condition number |
+-------+------+------------------------------+
2 rows in set
例4:上記の例に基づき、現在診断領域には2つの条件があるため、同じ GET DIAGNOSTICS 文は正常に実行されます。
obclient> GET DIAGNOSTICS CONDITION 2 @var2 = MESSAGE_TEXT;
Query OK, 0 rows affected
obclient> SELECT @var2;
+---------------------------+
| @var2 |
+---------------------------+
| Invalid condition number |
+---------------------------+
1 row in set
診断領域スタックの動作原理
診断領域がスタックにプッシュされると、最初の(現在の)診断領域は2番目の(スタック上の)診断領域となり、新しい現在の診断領域がそのコピーとして作成されます。以下の場合、診断領域はスタックにプッシュまたはスタックからポップされます:
ストアドプログラムの実行
プログラムの実行前に診断領域にプッシュされ、その後診断領域がポップされます。ストアドプログラムがハンドラーの実行中に終了した場合、複数の診断領域をポップできます。これは、適切なハンドラーが例外を発生させなかった場合、またはハンドラー内の
RETURNによって発生した場合です。その後、ポップされた診断領域内のアラートまたはエラー条件が現在の診断領域に追加されます。ただし、トリガーの場合はエラー条件のみが追加されます。ストアドプログラムが終了すると、呼び出し元は現在の診断領域でこれらの条件を確認できます。
ストアドプログラム内で条件ハンドラーを実行する場合
条件ハンドラーのアクティベーションによりプッシュが発生した場合、スタック上の診断領域はプッシュ前の現在の領域(ストアドプログラム内)です。新しい現在の診断領域はハンドラーの現在の診断領域です。
GET [CURRENT] DIAGNOSTICSおよびGET STACKED DIAGNOSTICSは、ハンドラー内で現在(ハンドラー)およびスタック(ストアドプログラム)の診断領域の内容にアクセスするために使用できます。最初は同じ結果を返しますが、ハンドラー内で実行される文は現在の診断領域を変更し、一般的なルールに従ってその内容をクリアします。RESIGNALを除き、ハンドラー内で実行される文はスタック上の診断領域を変更することはできません。ハンドラーの実行が成功した場合、現在の(ハンドラー)診断領域がポップされ、スタック(ストアドプログラム)診断領域が再び現在の診断領域となります。ハンドラー実行中にハンドラー診断領域に追加された条件は、現在の診断領域に追加されます。
RESIGNALの実行ストアドプログラム内の複合文で条件ハンドラーを実行する際、
RESIGNAL文は利用可能なエラー条件情報を渡すために使用されます。RESIGNALは情報を渡す前に一部または全部の情報を変更し、スタック診断領域を変更する可能性があります。詳細については RESIGNAL を参照してください。