MySQL 8.0 リファレンスマニュアル MySQL NDB Cluster 8.0 を含む

このページは機械翻訳したものです。

13.6.7.6 ハンドラのスコープに関するルール

ストアドプログラムには、そのプログラム内で特定の条件が発生したときに呼び出されるハンドラを含めることができます。 各ハンドラの適用性は、プログラム定義の中でのそのハンドラの場所や、そのハンドラが処理する 1 つまたは複数の条件によって異なります。

複数のハンドラを異なるスコープ内で、かつ異なる特定性で宣言できます。 たとえば、外側のブロックには特定の MySQL エラーコードハンドラが、また内側のブロックには一般的な SQLWARNING ハンドラが存在する可能性があります。 あるいは、特定の MySQL エラーコードのハンドラと、一般的な SQLWARNING クラスのハンドラが同じブロック内に存在することもあります。

あるハンドラがアクティブ化されるかどうかは、それ自体のスコープや条件値だけでなく、ほかにどのようなハンドラが存在するかによっても異なります。 ストアドプログラム内で条件が発生すると、サーバーは、適用可能なハンドラを現在のスコープ (現在の BEGIN ... END ブロック) 内で検索します。 適用可能なハンドラが存在しない場合は、連続した包含する各スコープ (ブロック) 内のハンドラに関して外側に検索を続行します。 特定のスコープで適用可能なハンドラを 1 つ以上見つけると、サーバーは、次の条件の優先順位に基づいてそれらのハンドラから選択します。

ハンドラ選択ルールの 1 つの側面として、複数の適用可能なハンドラが異なるスコープ内に存在する場合は、もっともローカルなスコープを持つハンドラが外側のスコープにあるハンドラより (それが、より具体的な条件のハンドラであっても) 優先される点があります。

ある条件が発生したときに適切なハンドラが存在しない場合、実行されるアクションはその条件のクラスによって異なります。

次の例は、MySQL によってハンドラ選択ルールがどのように適用されるかを示しています。

次のプロシージャーには 2 つのハンドラが含まれています。つまり、存在しないテーブルを削除しようとする試みに対して発生する特定の SQLSTATE 値 ('42S02') 用に 1 つと、一般的な SQLEXCEPTION クラス用に 1 つです。

CREATE PROCEDURE p1()
BEGIN
  DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
    SELECT 'SQLSTATE handler was activated' AS msg;
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;

  DROP TABLE test.t;
END;

両方のハンドラが同じブロック内で宣言され、同じスコープを持っています。 ただし、SQLSTATE ハンドラは SQLEXCEPTION ハンドラより優先されるため、テーブル t が存在しない場合、DROP TABLE ステートメントは SQLSTATE ハンドラをアクティブ化する条件を発生させます。

mysql> CALL p1();
+--------------------------------+
| msg                            |
+--------------------------------+
| SQLSTATE handler was activated |
+--------------------------------+

次のプロシージャーにも、同じ 2 つのハンドラが含まれています。 ただし、今回は、DROP TABLE ステートメントと SQLEXCEPTION ハンドラが SQLSTATE ハンドラに対して内側のブロック内にあります。

CREATE PROCEDURE p2()
BEGIN -- outer block
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
      SELECT 'SQLEXCEPTION handler was activated' AS msg;

    DROP TABLE test.t; -- occurs within inner block
  END;
END;

この場合は、条件が発生した場所に対してよりローカルなハンドラが優先されます。 SQLSTATE ハンドラより一般的であるにもかかわらず、SQLEXCEPTION ハンドラがアクティブ化されます。

mysql> CALL p2();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+

次のプロシージャーでは、ハンドラの 1 つが、DROP TABLE ステートメントのスコープに対して内側のブロック内で宣言されています。

CREATE PROCEDURE p3()
BEGIN -- outer block
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  END;

  DROP TABLE test.t; -- occurs within outer block
END;

もう一方のハンドラが DROP TABLE によって発生した条件のスコープ内にないため、SQLEXCEPTION ハンドラのみが適用されます。

mysql> CALL p3();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+

次のプロシージャーでは、両方のハンドラが、DROP TABLE ステートメントのスコープに対して内側のブロック内で宣言されています。

CREATE PROCEDURE p4()
BEGIN -- outer block
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
      SELECT 'SQLEXCEPTION handler was activated' AS msg;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  END;

  DROP TABLE test.t; -- occurs within outer block
END;

DROP TABLE のスコープ内にないため、どちらのハンドラも適用されません。 このステートメントによって発生した条件は未処理になり、プロシージャーをエラーで終了させます。

mysql> CALL p4();
ERROR 1051 (42S02): Unknown table 'test.t'