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.