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 はまた、SIGNAL ステートメントの SQLSTATE パラメータから取得した値を RETURNED_SQLSTATE に設定します。これは、SET 句内で直接設定するのではなく、SIGNAL によって行われます。
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 を参照してください。