Реализация обработки ошибок T-SQL
Ошибка указывает на проблему или заметную неполадку, возникающую во время операции с базой данных. Ошибки могут создаваться ядром СУБД SQL Server в ответ на событие или сбой на уровне системы; или вы можете создать ошибки приложения в коде Transact-SQL.
Элементы ошибок ядра СУБД
Независимо от причины каждая ошибка состоит из следующих элементов:
- Номер ошибки — уникальный номер, определяющий конкретную ошибку.
- Сообщение об ошибке — текст, описывающий ошибку.
- Серьезность — числовое указание серьезности от 1 до 25.
- Состояние — внутренний код состояния для условия ядра СУБД.
- Процедура — имя хранимой процедуры или триггера, в котором произошла ошибка.
- Номер строки — какая инструкция в пакете или процедуре вызвала ошибку.
Системные ошибки
Системные ошибки предопределяются, и их можно просмотреть в системном представлении sys.messages . При возникновении системной ошибки SQL Server может выполнять автоматическое исправление в зависимости от серьезности ошибки. Например, при возникновении ошибки с высокой серьезностью SQL Server может отключить базу данных или даже остановить службу ядра СУБД.
Пользовательские ошибки
Вы можете создавать ошибки в коде Transact-SQL для реагирования на условия, связанные с приложением, или настраивать сведения, отправленные клиентским приложениям в ответ на системные ошибки. Эти ошибки приложения можно определить непосредственно там, где они создаются, или предопределить в таблице sys.messages вместе с системными ошибками. Номера ошибок, используемые для пользовательских ошибок, должны иметь значение 50001 или больше.
Чтобы добавить настраиваемое сообщение об ошибке в sys.messages, используйте sp_addmessage. Пользователь сообщения должен быть членом предопределенных ролей сервера sysadmin или serveradmin.
Это синтаксис sp_addmessage:
sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg'
[ , [ @lang= ] 'language' ]
[ , [ @with_log= ] { 'TRUE' | 'FALSE' } ]
[ , [ @replace= ] 'replace' ]
Ниже приведен пример пользовательского сообщения об ошибке с помощью этого синтаксиса:
sp_addmessage 50001, 10, N’Unexpected value entered’;
Кроме того, можно определить пользовательские сообщения об ошибках. Члены роли сервера sysadmin могут использовать дополнительный параметр @with_log. Если задано значение TRUE, ошибка также будет записана в журнале приложений Windows. Любое сообщение, записанное в журнал приложений Windows, также записывается в журнал ошибок SQL Server. Будьте разумны с использованием @with_log параметра, так как сетевые и системные администраторы, как правило, не любят приложения, которые являются "чатными" в системных журналах. Однако, если ошибка должна быть перехвачена оповещением, её необходимо сначала записать в журнал приложений Windows.
Замечание
Вызов системных ошибок не поддерживается.
Сообщения можно заменить, не удаляя их сначала с помощью @replace параметра = "заменить".
Сообщения настраиваются, и разные могут быть добавлены для одного и того же номера ошибки для нескольких языков на основании значения language_id.
Замечание
Сообщения на английском языке имеют language_id 1033.
Генерация ошибок с помощью RAISERROR
Для возврата информации или предупреждающих сообщений в приложения можно использовать как PRINT, так и RAISERROR. RAISERROR позволяет приложениям вызывать ошибку, которая затем может быть обработана вызывающим процессом.
RAISERROR
Возможность вызывать ошибки в T-SQL упрощает обработку ошибок в приложении, так как она отправляется как любая другая системная ошибка. RAISERROR используется для:
- Помощь в устранении проблем с кодом T-SQL.
- Проверьте значения данных.
- Возвращайте сообщения, содержащие переменный текст.
Замечание
Использование инструкции PRINT аналогично возникновению ошибки серьезности 10.
Ниже приведен пример пользовательского сообщения об ошибке с помощью RAISERROR.
RAISERROR (N'%s %d', -- Message text,
10, -- Severity,
1, -- State,
N'Custom error message number',
2)
При активации возвращается:
Custom error message number 2
В предыдущем примере %d является заполнителем для числа и %s является заполнителем строки. Кроме того, следует отметить, что номер сообщения не был указан. При возникновении ошибок со строками сообщений с помощью этого синтаксиса всегда имеется номер ошибки 50000.
Генерация ошибок с помощью THROW
Инструкция THROW предлагает более простой метод повышения ошибок в коде. Ошибки должны иметь номер ошибки не менее 50000.
БРОСАТЬ
THROW отличается от RAISERROR несколькими способами:
- Ошибки, вызываемые THROW, всегда имеют уровень серьезности 16.
- Сообщения, возвращаемые методом THROW, не связаны с записями в sys.sysmessages.
- Ошибки, возникающие с помощью THROW, вызывают прерывание транзакции только при использовании в сочетании с SET XACT_ABORT ON и сеанс завершается.
THROW 50001, 'An Error Occured',0
Запись кодов ошибок с помощью @@Error
Большинство традиционных кодов обработки ошибок в приложениях SQL Server созданы с помощью @@ERROR. Структурированная обработка исключений появилась в SQL Server 2005 и предоставляет надежную альтернативу использованию @@ERROR. Он будет рассмотрен в следующем занятии. Большой объем существующего кода обработки ошибок SQL Server основан на @@ERROR, поэтому важно понимать, как работать с ним.
Ошибка
@@ERROR — это системная переменная, содержащая номер последней ошибки. Одна из важных проблем с @@ERROR заключается в том, что значение, которое оно содержит, быстро сбрасывается по мере выполнения каждой дополнительной инструкции.
Например, рассмотрим следующий код:
RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO
Вы можете ожидать, что при выполнении кода он вернет номер ошибки в напечатанной строке. Однако при выполнении кода возвращается следующее:
Msg 50000, Level 16, State 1, Line 1
Message
Error=0
Возникла ошибка, но было выведено сообщение "Error=0". В первой строке выходных данных вы увидите, что ошибка, как ожидалось, была фактически 50000 с сообщением, переданным в RAISERROR. Это связано с тем, что оператор IF, следующий за инструкцией RAISERROR, был выполнен успешно и вызвал сброс значения @@ERROR. По этой причине при работе с @@ERROR важно записать номер ошибки в переменную сразу после ее возникновения, а затем продолжить обработку с переменной.
Просмотрите следующий код, демонстрирующий следующее:
DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));
При выполнении этого кода он возвращает следующие выходные данные:
Msg 50000, Level 16, State 1, Line 2
Message
Error=50000
Номер ошибки правильно сообщается сейчас.
Централизованная обработка ошибок
Одна из других важных проблем с использованием @@ERROR для обработки ошибок заключается в том, что трудно централизировать код T-SQL. Обработка ошибок, как правило, разбросана по всему коду. Можно было бы централизировать обработку ошибок с помощью @@ERROR в некоторой степени с помощью меток и инструкций GOTO. Тем не менее, большинство разработчиков сегодня посчитали бы это плохой практикой программирования.
Создание оповещений об ошибках
Для определенных категорий ошибок администраторы могут создавать оповещения SQL Server, так как они хотят получать уведомления сразу после их возникновения. Это может даже применяться к определяемым пользователем сообщениям об ошибках. Например, при заполнении журнала транзакций может потребоваться создать оповещение. Оповещения обычно используются для привлечения внимания администраторов к ошибкам высокой степени серьезности (например, 19 и выше).
Создание оповещений
Оповещения можно создавать для определенных сообщений об ошибках. Служба оповещений работает путем регистрации в качестве службы обратного вызова в службе ведения журнала событий. Это означает, что оповещения работают только на зафиксированных ошибках.
Существует два способа, как сделать так, чтобы ошибка вызвала оповещение: используйте параметр WITH LOG при генерации ошибки или измените сообщение, чтобы оно было зарегистрировано, выполнив sp_altermessage. Параметр WITH LOG влияет только на текущую инструкцию. Использование sp_altermessage изменяет поведение обработки ошибок для всех будущих использований. Модификация системных ошибок с помощью sp_altermessage возможна только начиная с SQL Server 2005 с пакетом обновления 3 (SP3) или SQL Server 2008 с пакетом обновления 1 (SP1).