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 H1stmt1; 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.