Spec-Zone.ru › MySQL 8.4

15.6.7.6 Правила области действия обработчиков

Хранимые программы могут содержать обработчики, которые вызываются при возникновении определенных условий внутри программы. Применимость каждого обработчика зависит от его местоположения в определении программы и от условия или условий, которые он обрабатывает:

  • Обработчик, объявленный в блоке BEGIN ... END, находится в области действия только для SQL-утверждений, следующих за объявлениями обработчиков в блоке. Если сам обработчик вызывает условие, он не может обработать это условие, и не могут обработать его другие обработчики, объявленные в блоке. В приведенном ниже примере обработчики H1 и H2 находятся в области действия для условий, вызванных утверждениями stmt1 и stmt2. Но ни H1, ни H2 не находятся в области действия для условий, вызванных в теле H1 или H2.

    BEGIN -- outer block
      DECLARE EXIT HANDLER FOR ...;  -- handler H1
      DECLARE EXIT HANDLER FOR ...;  -- handler H2
      stmt1;
      stmt2;
    END;
    
  • Обработчик находится в области действия только для блока, в котором он объявлен, и не может быть активирован для условий, возникающих за пределами этого блока. В приведенном ниже примере обработчик H1 находится в области действия для stmt1 во внутреннем блоке, но не для stmt2 во внешнем блоке:

    BEGIN -- outer block
      BEGIN -- inner block
        DECLARE EXIT HANDLER FOR ...;  -- handler H1
        stmt1;
      END;
      stmt2;
    END;
    
  • Обработчик может быть специфическим или общим. Специфический обработчик предназначен для кода ошибки MySQL, значения SQLSTATE или имени условия. Общий обработчик предназначен для условия в классе SQLWARNING, SQLEXCEPTION или NOT FOUND. Специфичность условия связана с приоритетом условия, как описано ниже.

Можно объявить несколько обработчиков в разных областях действия и с разной специфичностью. Например, во внешнем блоке может быть обработчик для конкретного кода ошибки MySQL, а во внутреннем блоке — общий обработчик SQLWARNING. Или в одном блоке могут быть обработчики для конкретного кода ошибки MySQL и общего класса SQLWARNING.

Активация обработчика зависит не только от его собственной области действия и значения условия, но и от присутствия других обработчиков. Когда в хранимой программе возникает условие, сервер ищет применимые обработчики в текущей области действия (текущий блок BEGIN ... END). Если применимых обработчиков нет, поиск продолжается во внешней области действия с обработчиками в каждом последующем содержащем блоке (блоке). Когда сервер находит один или несколько применимых обработчиков в данной области действия, он выбирает среди них на основе приоритета условия:

  • Обработчик кода ошибки MySQL имеет приоритет над обработчиком значения SQLSTATE.

  • Обработчик значения SQLSTATE имеет приоритет над общими обработчиками SQLWARNING, SQLEXCEPTION или NOT FOUND.

  • Обработчик SQLEXCEPTION имеет приоритет над обработчиком SQLWARNING.

  • Возможно наличие нескольких применимых обработчиков с одинаковым приоритетом. Например, утверждение может сгенерировать несколько предупреждений с разными кодами ошибок, для каждого из которых существует специфичный для ошибки обработчик. В этом случае выбор обработчика, который активирует сервер, не является детерминированным и может изменяться в зависимости от обстоятельств, при которых возникает условие.

Следствием правил выбора обработчиков является то, что если несколько применимых обработчиков встречаются в разных областях действия, обработчики с самой локальной областью действия имеют приоритет над обработчиками во внешних областях действия, даже над теми, которые предназначены для более специфических условий.

Если при возникновении условия нет подходящего обработчика, действия зависят от класса условия:

  • Для условий SQLEXCEPTION хранимая программа завершается в утверждении, которое вызвало условие, как если бы существовал обработчик EXIT. Если программа была вызвана другой хранимой программой, вызывающая программа обрабатывает условие, используя правила выбора обработчиков, применимые к собственным обработчикам.

  • Для условий SQLWARNING программа продолжает выполнение, как если бы существовал обработчик CONTINUE.

  • Для условий NOT FOUND, если условие было вызвано обычным способом, действие — CONTINUE. Если оно было вызвано с помощью SIGNAL или RESIGNAL, действие — EXIT.

Следующие примеры демонстрируют, как MySQL применяет правила выбора обработчиков.

Эта процедура содержит два обработчика: один для конкретного значения SQLSTATE ('42S02'), которое возникает при попытке удалить несуществующую таблицу, и один для общего класса SQLEXCEPTION:

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 |
+--------------------------------+

Эта процедура содержит те же два обработчика. Но на этот раз утверждение 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;

В этом случае обработчик, который более локален к тому месту, где возникает условие, имеет приоритет. Активируется обработчик SQLEXCEPTION, даже если он более общий, чем обработчик SQLSTATE:

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

В этой процедуре один из обработчиков объявлен в блоке, внутреннем по отношению к области действия утверждения 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;

Применяется только обработчик SQLEXCEPTION, потому что другой не находится в области действия для условия, вызванного DROP TABLE:

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'

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/handler-scope.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API