Обработка ошибок хранимой процедуры MySQL

Я считаю, что в MySQL нет ничего доступного в MySQL, который позволяет получить доступ к SQLSTATE последнего исполняемого оператора в хранимой процедуре MySQL. Это означает, что при генерировании общего SQLException в хранимой процедуре трудно/невозможно получить точный характер ошибки.

Есть ли у кого-нибудь обходной путь для получения SQLSTATE ошибки в хранимой процедуре MySQL, которая не включает объявление обработчика для всех возможных SQLSTATE?

Например, представьте, что я пытаюсь вернуть error_status, который выходит за рамки общего "SQLException, произошедшего где-то в этом блоке BEGIN....END", в следующем:

DELIMITER $$

CREATE PROCEDURE `myProcedure`(OUT o_error_status varchar(50))
MY_BLOCK: BEGIN

 DECLARE EXIT handler for 1062 set o_error_status := "Duplicate entry in table";
 DECLARE EXIT handler for 1048 set o_error_status := "Trying to populate a non-null column with null value"; 
-- declare handlers ad nauseum here....

 DECLARE EXIT handler for sqlexception set o_error_status:= "Generic SQLException. You'll just have to figure out the SQLSTATE yourself...." ;

-- Procedure logic that might error to follow here...

END MY_BLOCK$$

Любые советы?

PS Я запускаю MySQL 5.1.49

Ответ 2

Я считаю, что в MySQL нет ничего доступного в MySQL, который позволяет получить доступ к SQLSTATE последнего исполняемого оператора в хранимой процедуре MySQL. Это означает, что... трудно/невозможно определить точный характер ошибки.

К счастью, это не так.

SHOW ERRORS LIMIT 1   -- for SQL-state > 2
SHOW WARNINGS LIMIT 1 -- for SQL-state 1,2

Покажет последнюю ошибку или предупреждение.

Чтобы предотвратить перечисление каждой ошибки, вы можете обрабатывать класс SQL-ошибок:

SQLWARNING является сокращением для класса значений SQLSTATE, начинающегося с '01'.

NOT FOUND - это сокращение для класса значений SQLSTATE, начинающегося с '02'. Это актуально только в контексте курсоров и используется для контроля того, что происходит, когда курсор достигает конца набора данных. Если больше строк не доступно, возникает условие "Нет данных" с значением SQLSTATE 02000. Чтобы обнаружить это условие, вы можете настроить для него обработчик (или для НЕ НАЙДЕНО). Пример показан в разделе 12.7.5 "Курсоры". Это условие также возникает для операторов SELECT... INTO var_list, которые не извлекают строки.

SQLEXCEPTION является сокращением для класса значений SQLSTATE, которые не начинаются с '00', '01' или '02'.

Итак, для обработки исключения вам нужно только:

DECLARE EXIT HANDLER FOR SQLSTATE SQLEXCEPTION .....;

Ссылки:
http://dev.mysql.com/doc/refman/5.5/en/signal.html
http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html

Ответ 3

Я делаю следующее обходное решение: используя SELECT для провоцирования ошибки. Например:

SELECT RAISE_ERROR_unable_to_update_basket;

Это приведет к следующему сообщению об ошибке (пример):

ERROR 1054 (42S22): Unknown column 'RAISE_ERROR_unable_to_update_basket' in 'field list'

Я завершу свой вызов хранимой процедуре в try {...} catch {...} и теперь могу обработать эту ошибку. Это, конечно же, будет работать только на провоцирование пользовательских сообщений об ошибках внутри хранимой процедуры и не будет обрабатывать любые ошибки SQL или базы данных, которые могут возникнуть (из-за записи с дубликат-ключ). В последнем случае вы можете обходить это, используя решение Johan.