|
Программирование >> Программирование баз данных
INSERT INTO Sales.StoreContact (CustomerlD, ContactID, ContactTypelD) VALUES (©CustomerlD, ©ContactID, ©ContactTypelD) SET ©Error = ©©ERROR IF ©Error = 0 PRINT New Record Inserted ELSE BEGIN IF ©Error = 547 -- Нарушение ограничения внешнего ключа. Об этой ошибке следует обязательно сообщить PRINT At least one provided parameter was not found. Correct and retry ELSE -- Какая-то неизвестная ошибка PRINT Unknown error occurred. Please contact your system admin В первую очередь попытаемся выполнить этот код, задавая допустимые значения: EXEC spInsertValidatedStoreContact 1, 1, 11 Эта операция вставки была выполнена успешно, поскольку не были обнаружены какие-либо условия возникновения ошибок (и не должны были быть обнаружены): (1 row(s) affected) New Record Inserted A теперь рассмотрим ситуацию, в которой попытка выполнения хранимой процедуры должна окончиться неудачей: EXEC SpInsertValidatedStoreContact О, 1, 11 В данном случае обнаруживается не только сообщение, сформированное СУБД SQL Server, но и сообщение, подготовленное с помощью используемых в коде средств перехвата ошибок (обратите внимание на то, что удалить сообщение СУБД SQL Server не представляется возможным): Msg 547, Level 16, State О, Procedure spI];isertValidatedStoreContact, Line 11 The INSERT statement conflicted with the FOREIGN KEY constraint FK StoreContact Store CustomerID . The conflict occurred in database AdventureWorks , table Sales.Store , column CustomerlD. The statement has been terminated. At least one provided parameter was not found. Correct and retry Вполне очевидно, что в данном случае удалось обнаружить и перехватить ошибку без использования блока TRY/САТСН. Теперь перейдем к рассмотрению примера, который показывает, в чем преимущества блока TRY/CATCH; в данном случае демонстрируется такая ситуация, что TRY/CATCH действует вполне приемлемо, а встроенные средства проверки ошибок терпят неудачу. Чтобы полностью рассмотреть данную ситуацию, достаточно воспользоваться примером применения блока TRY/САТСН, который был приведен в главе, посвященной созданию сценария. Этот запрос выглядит следующим образом: BEGIN TRY Предпринимается попытка создать таблицу CREATE TABLE OurlFTest( Coll int PRIMARY KEY END TRY BEGIN CATCH -- Возникла какая-то ошибка; попытаемся определить, известен ли способ --ее исправления DECLARE ©ErrorNo int, ©Severity tinyint, ©State smallint, ©LineNo int, ©Message nvarchar(4000) SELECT ©ErrorNo = ERROR NUMBER(), ©Severity = ERROR SEVERITY(), ©State = ERROR STATE(), ©LineNo = ERROR LINE (), ©Message = ERROR MESSAGE() IF ©ErrorNo = 2714 -- Обнаруживается ошибка, указывающая на то, что объект -- уже существует, но в этом нет ничего неожиданного PRINT WARNING: Skipping CREATE as table already exists ELSE -- Ho эта ошибка не может быть распознана, поэтому о ней необходимо -- сообщить и больше ничего не предпринимать RAISERROR(©Message, 16, 1 ) END CATCH Приведенный выше оператор выполняется вполне успешно. Но после того как предпринимается попытка применить в этом сценарии встроенные средства проверки ошибок, возникает нарушение в работе: CREATE TABLE OurlFTest( Coll int PRIMARY KEY IF ©©ERROR 1= 0 PRINT Problems! ELSE PRINT Everything went OKI После вызова этого сценария на вьшолнение (его потребуется выполнить дважды, чтобы возникла ошибка, если таблица еще не создана) сразу же обнаруживается, что СУБД SQL Server полностью прекращает обработку сценария без блока TRY после обнаружения той конкретной ошибки, которая здесь вырабатывается: Msg 2714, Level 16, State б. Line 2 There is already an object named OurlFTest in the database. Обратите внимание на то, что возможность вьшолнения приведенных в сценарии операторов PRINT исключена, поскольку еще до этого СУБД SQL Server прекращает обработку сценария. Таким образом, блок TRY/CATCH позволяет перехватить и обработать данную ошибку, а при использовании встроенных средств проверки ошибок попытки перехватить ошибку оканчиваются неудачей. Активизация ошибок вручную Иногда возникают такие ситуации, которые с точки зрения эксплуатации приложения рассматриваются как ошибки, а что касается самой СУБД SQL Server, то они не рассматриваются как таковые, но для обработки этих ошибок желательно применить механизмы самой СУБД. Например, предположим, что в предьщущем примере возврат значения -10 О О является признаком возникновения ошибки и об этом передается сообщение пользователю. Но вместо этого хотелось бы, чтобы в клиентском приложении была активизирована ошибка этапа прогона, а сообщение о данной ошибке было бы применено для вызова обработчика ошибок и осуществления соответствующих действий. Для этого в языке T-SQL используется команда RAISERROR. Синтаксис вызова этой команды - довольно простой: RA.ISERROR (<message ID message string>, <severity>, <state> [, <argument> [,<...n>]] ) [WITH option [, . . .n] ] Идентификатор сообщения или строка сообщения Параметр с обозначением идентификатора сообщения или строки сообщения позволяет указать, какое сообщение должно быть передано в клиентскую программу. Если используется идентификатор сообщения, то создается активизированное вручную сообщение об ошибке с заданным идентификатором и текстом, соответствующим идентификатору и находящимся в таблице sysmessages базы данных master. Для просмотра списка заранее заданных сообщений СУБД SQL Server можно в любое время вызвать на выполнение оператор SELECT * FROM mastersysMessages. В формируемый при этом список входят также все сообщения, введенные в систему вручную с помощью хранимой процедуры sp addmessage или программы Enterprise Manager. Таким образом, чтобы воспользоваться идентификатором сообщения, необходимо передать его на постоянное хранение вместе с соответствующим сообщением в таблицу sysmessages: RAISERROR (Hi there, Im an error, 1, 1) При этом формируется следующее довольно простое сообщение об ошибке: Msg 50000, Level 1, State 50000 Hi there, Im an error Обратите внимание на то, что система присвоила этому сообщению идентификатор 50000, даже несмотря на то, что он не быя задан в предыдущем операторе RAISERROR. Этот идентификатор ошибки присваивается по умолчанию любому сообщению об ошибке, введенному непосредственно в операторе RAISERROR, а не извлеченному из таблицы sysmes sages. Вместо этого применяемого по умолчанию идентификатора ошибки можно явно задать другой идентификатор с помощью опции WITH SETERROR. Степень серьезности Этой теме уже было уделено определенное внимание при рассмотрении конструкции TRY/САТСН в главе, посвященной созданию сценариев. Понятие степени серьезности ошибки (severity) входит в состав терминологии, связанной со многими серверами Windows. Степень серьезности ошибки является указанием на то, какие меры следует принимать с учетом этой ошибки. Но система обозначений степеней серьезности ошибок в СУБД SQL Server требует более внимательного изучения. Эти обозначения охватывают широкий спектр сообщений об ошибках, включая те, которые по существу являются информационными (со значениями степеней серьезности 1-18), относятся к системному уровню (19-25) и даже рассматриваются как катастрофические (20-25). При активизации ошибки со степенью серьезности 19 или выше (системный уровень) необходимо также задавать опцию WITH LOG. При возникновении ошибок со степенями серьезности 20 и выше автоматически завершается работа пользовательских соединений. (Следуетучитывать, что при этом пользователи выражают бурное возмущение!) Рассмотрим более подробно систему обозначений степеней серьезности, применяемую в СУБД SQL Server, которая, как )е было сказано, заслуживает более внимательного изучения. Фактически действия, предпринимаемые в СУБД SQL Server, в за-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |