Обработка исключительных ситуаций в javascript

Обработка FileNotFoundError

При работе с файлами в Python часто возникает ошибка .

В следующем примере мы попытаемся открыть файл my_file.txt, указав его путь в функции . Мы хотим прочитать файл и вывести его содержимое.

Однако мы еще не создали этот файл в указанном месте.

my_file = open("/content/sample_data/my_file.txt")
contents = my_file.read()
print(contents)

Поэтому, попытавшись запустить приведенный выше фрагмент кода, мы получим :

---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-4-4873cac1b11a> in <module>()
----> 1 my_file = open("my_file.txt")

FileNotFoundError:  No such file or directory: 'my_file.txt'

А с помощью и мы можем сделать следующее:

  • Попробуем открыть файл в блоке .
  • Обработаем в блоке , сообщив пользователю, что он попытался открыть несуществующий файл.
  • Если блок завершается успешно и файл действительно существует, прочтем и распечатаем содержимое.
  • В блоке закроем файл, чтобы не терять ресурсы. Файл будет закрыт независимо от того, что происходило на этапах открытия и чтения.
try:
    my_file = open("/content/sample_data/my_file.txt")
except FileNotFoundError:
    print(f"Sorry, the file does not exist")
else:
    contents = my_file.read()
    print(contents)
finally:
    my_file.close()

Обратите внимание: мы обработали ошибку как исключение, и программа завершает работу, отображая следующее сообщение:

Sorry, the file does not exist

Теперь рассмотрим случай, когда срабатывает блок . Файл my_file.txt теперь присутствует по указанному ранее пути.

Вот содержимое этого файла:

Теперь повторный запуск нашего кода работает должным образом.

На этот раз файл my_file.txt присутствует, поэтому запускается блок и содержимое распечатывается, как показано ниже:

Надеемся, теперь вы поняли, как обрабатывать исключения при работе с файлами.

Example SQL Try Catch in SQL Server 2005 / SQL Server 2008

One of the most common sql errorsI experience is related with concatenating sql variables.
When one of the concatenated tsql variables is an integer number for example, the conversion failed error message is raised by the SQL Server engine.

The error message I will try to handle is like as shown below:Msg 245, Level 16, State 1, Line 5Conversion failed when converting the varchar value ‘{0}’ to data type int.

The first error that we can try to build an error handler is this conversion errors experienced during string concatenations in sql.

Code

An other very common example can be considered as the divide by zero errors.
The error message is «Divide by zero error encountered.»

Code

The test

Setup

This quick script will create our table with data and our table which will be used to log errors.

CREATE TABLE dbo.ToBeBlocked (id TINYINT NOT NULL)
CREATE TABLE dbo.Failures (id TINYINT IDENTITY(1,1) NOT NULL
, errorMsg VARCHAR(500) NOT NULL)
GO
INSERT INTO dbo.ToBeBlocked (id) VALUES (1);
INSERT INTO dbo.ToBeBlocked (id) VALUES (2);
GO 10

Script 1

In this script we have the Try-Catch block seen above. I’ve added a select and an update to help us setup a deadlock condition. The DEADLOCK_PRIORITY and REPEATABLE READ isolation level ensures that we take a lock on all rows in the table and try to update them after another script has stepped in the way. The WAITFOR DELAY is used to give time for you to run Script 2 in another query window before the update fires. Finally, it will query the Failures table to see if we inserted any rows.

SET DEADLOCK_PRIORITY LOW

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRY

BEGIN TRANSACTION

SELECT id FROM dbo.ToBeBlocked;

— Give us a chance to run the other script
— to cause a deadlock
WAITFOR DELAY ’00:00:05′;

UPDATE dbo.ToBeBlocked
SET id = 3
WHERE id = 2

COMMIT

END TRY
BEGIN CATCH

DECLARE @errMsg VARCHAR(500) = ERROR_MESSAGE()
, @errState INT = ERROR_STATE()
, @errSeverity int = ERROR_SEVERITY()

INSERT INTO dbo.Failures (errorMsg)
VALUES (@errMsg)

RAISERROR(@errMsg, @errSeverity, @errState);

END CATCH

SELECT * FROM dbo.Failures

Script 2

This script will be executed during the 5 sec delay from running Script 1. This will cause our deadlock and become the victor because Script 1’s DEADLOCK_PRIORITY is set to LOW, making it the victim.

BEGIN TRANSACTION

UPDATE dbo.ToBeBlocked
SET id = 2
WHERE id = 2;

COMMIT

Запрет на передачу ошибок

Иногда вы знаете, что функции throw или методы не сгенерируют ошибку во время исполнения. В этих случаях, вы можете написать try! перед выражением для запрета передачи ошибки и завернуть вызов в утверждение того, что ошибка точно не будет сгенерирована. Если ошибка на самом деле сгенерирована, вы получите сообщение об ошибке исполнения.

Например, следующий код использует loadImage(atPath: ) функцию, которая загружает ресурс изображения по заданному пути или генерирует ошибку, если изображение не может быть загружено. В этом случае, поскольку изображение идет вместе с приложением, сообщение об ошибке не будет сгенерировано во время выполнения, поэтому целесообразно отключить передачу ошибки.

Установка действий по очистке (Cleanup)

Вы используете оператор defer для выполнения набора инструкций перед тем как исполнение кода оставит текущий блок. Это позволяет сделать любую необходимую очистку, которая должна быть выполнена, независимо от того, как именно это произойдет — либо он покинет из-за сгенерированной ошибки или из-за оператора, такого как break или return. Например, вы можете использовать defer, чтобы удостовериться, что файл дескрипторов закрыт и выделенная память вручную освобождена.

Оператор defer откладывает выполнение, пока не происходит выход из текущей области. Этот оператор состоит из ключевого слова defer и выражений, которые должны быть выполнены позже. Отложенные выражения могут не содержать кода, изменяющего контроль исполнения изнутри наружу, при помощи таких операторов как break или return, или просто генерирующего ошибку. Отложенные действия выполняются в обратном порядке, как они указаны, то есть, код в первом операторе defer выполняется после кода второго, и так далее.

Приведенный выше пример использует оператор defer, чтобы удостовериться, что функция open(_: ) имеет соответствующий вызов и для close(_: ).

Конструкция TRY CATCH в T-SQL

TRY CATCH – это конструкция языка Transact-SQL для обработки ошибок. Все, что Вы хотите проверять на ошибки, т.е. код в котором могут возникнуть ошибки, Вы помещаете в блок TRY. Начало данного блока обозначается инструкцией BEGIN TRY, а окончание блока, соответственно, END TRY.

Все, что Вы хотите выполнять в случае появления ошибки, т.е. те инструкции, которые должны выполниться, если в блоке TRY возникла ошибка, Вы помещаете в блок CATCH, его начало обозначается BEGIN CATCH, а окончание END CATCH. Если никаких ошибок в блоке TRY не возникло, то блок CATCH пропускается и выполняются инструкции, следующие за ним. Если ошибки возникли, то выполняются инструкции в блоке CATCH, а после выполняются инструкции, следующие за данным блоком, иными словами, все инструкции, следующие за блоком CATCH, будут выполнены, если, конечно же, мы принудительно не завершили выполнение пакета в блоке CATCH.

Сам блок CATCH не передает никаких сведений об обнаруженных ошибках в вызывающее приложение, если это нужно, например, узнать номер или описание ошибки, то для этого Вы можете использовать инструкции SELECT, RAISERROR или PRINT в блоке CATCH.

Важные моменты про конструкцию TRY CATCH в T-SQL

  • Блок CATCH должен идти сразу же за блоком TRY, между этими блоками размещение инструкций не допускается;
  • TRY CATCH перехватывает все ошибки с кодом серьезности, большим 10, которые не закрывают соединения с базой данных;
  • В конструкции TRY…CATCH Вы можете использовать только один пакет и один блок SQL инструкций;
  • Конструкция TRY…CATCH может быть вложенной, например, в блоке TRY может быть еще одна конструкция TRY…CATCH, или в блоке CATCH Вы можете написать обработчик ошибок, на случай возникновения ошибок в самом блоке CATCH;
  • Оператор GOTO нельзя использовать для входа в блоки TRY или CATCH, он может быть использован только для перехода к меткам внутри блоков TRY или CATCH;
  • Обработка ошибок TRY…CATCH в пользовательских функциях не поддерживается;
  • Конструкция TRY…CATCH не обрабатывает следующие ошибки: предупреждения и информационные сообщения с уровнем серьезности 10 или ниже, разрыв соединения, вызванный клиентом, завершение сеанса администратором с помощью инструкции KILL.

Функции для получения сведений об ошибках

Для того чтобы получить информацию об ошибках, которые повлекли выполнение блока CATCH можно использовать следующие функции:

  • ERROR_NUMBER() – возвращает номер ошибки;
  • ERROR_MESSAGE() — возвращает описание ошибки;
  • ERROR_STATE() — возвращает код состояния ошибки;
  • ERROR_SEVERITY() — возвращает степень серьезности ошибки;
  • ERROR_PROCEDURE() — возвращает имя хранимой процедуры или триггера, в котором произошла ошибка;
  • ERROR_LINE() — возвращает номер строки инструкции, которая вызвала ошибку.

Если эти функции вызвать вне блока CATCH они вернут NULL.

Пример использования конструкции TRY…CATCH для обработки ошибок

Для демонстрации того, как работает конструкция TRY…CATCH, давайте напишем простую SQL инструкцию, в которой мы намеренно допустим ошибку, например, попытаемся выполнить операцию деление на ноль.

   
   --Начало блока обработки ошибок
   BEGIN TRY
        --Инструкции, в которых могут возникнуть ошибки
        DECLARE @TestVar1 INT = 10, 
                        @TestVar2 INT = 0, 
                        @Rez INT
        
        SET @Rez = @TestVar1 / @TestVar2

   END TRY
   --Начало блока CATCH
   BEGIN CATCH
        --Действия, которые будут выполняться в случае возникновения ошибки
        SELECT ERROR_NUMBER() AS ,
                   ERROR_MESSAGE() AS 
        SET @Rez = 0       
   END CATCH

   SELECT @Rez AS 

В данном случае мы выводим номер и описание ошибки с помощью функций ERROR_NUMBER() и ERROR_MESSAGE(), а также присваиваем переменной с итоговым результатом значение 0, как видим, инструкции после блока CATCH продолжают выполняться.

У меня на этом все, надеюсь, материал был Вам полезен, пока!

Нравится21Не нравится1

Points to Ponder – TRY CATCH Exception Handling – SQL Server

1.If T-SQL code within a BEGIN TRY…END TRY block is successfully executed without any failures then the T-SQL code in the BEGIN CATCH..END CATCH block is never executed.

2.BEGIN CATCH..END CATCH block must be immediately associated next to END TRY block, writing any statements in between END TRY and BEGIN CATCH is not allowed, this will raise a syntax error.

3.If T-SQL code within BEGIN TRY…END TRY block is successfully executed then the control is passed to the immediate T-SQL code written after END CATCH block if any.

4.If any error arises then after executing the statements in BEGIN CATCH … END CATCH block the control is passed to the immediate statement written after END CATCH block.

5.BEGIN TRY .. END TRY block can be nested, we can have exception handling
TRY…CATCH block inside a TRY CATCH block.

Смешанные процедурные инструкции

Процедурные расширения языка Transact-SQL также содержат следующие инструкции:

  • RETURN;

  • GOTO;

  • RAISEERROR;

  • WAITFOR

Инструкция RETURN выполняет ту же самую функцию внутри пакета, что и инструкция BREAK внутри цикла WHILE. Иными словами, инструкция RETURN останавливает выполнение пакета и начинает исполнение первой инструкции, следующей за пакетом.

Инструкция GOTO передает управление при выполнении пакета инструкции Transact-SQL внутри пакета, обозначенной маркером. Инструкция RAISEERROR выводит определенное пользователем сообщение об ошибке и устанавливает флаг системной ошибки. Номер ошибки в определяемом пользователем сообщении должен быть больше, чем 50 000, т.к. все номера ошибок меньшие или равные 50 000 определены системой и зарезервированы компонентом Database Engine. Значения номеров ошибок сохраняются в глобальной переменной @@error.

Инструкция WAITFOR определяет задержку на период времени (с параметром DELAY) или определенное время (с параметром TIME), на протяжении которой система должна ожидать, прежде чем исполнять следующую инструкцию пакета. Синтаксис этой инструкции выглядит следующим образом:

Параметр DELAY указывает системе баз данных ожидать, пока не истечет указанный период времени, а параметр TIME указывает точку во времени, в одном из допустимых форматов, до которой ожидать. Параметр TIMEOUT, за которым следует аргумент timeout, задает период времени в миллисекундах, в течение которого надо ожидать прибытия сообщения в очередь.

Транзакции в T-SQL

Транзакция – это команда или блок команд (инструкций), которые успешно завершаются как единое целое, при этом в базе данных все внесенные изменения фиксируются на постоянной основе, или отменяются, т.е. все изменения, внесенные любой командой, входящей в транзакцию, будут отменены. Другими словами, если одна команда или инструкция внутри транзакции завершилась с ошибкой, то все, что было отработано перед ней, также отменяется, даже если предыдущие команды завершились успешно.

Транзакции очень полезны и просто незаменимы в тех случаях, когда Вам необходимо реализовывать бизнес логику в базе данных Microsoft SQL Server, которая предполагает многошаговые операции, где каждый шаг логически связан с другими шагами.

По сути каждая отдельная инструкция языка T-SQL является транзакцией, это называется «Автоматическое принятие транзакций» или «Неявные транзакции», но также есть и явные транзакции, это когда мы сами явно начинаем транзакцию и также явно заканчиваем ее, т.е. делаем все это с помощью специальных команд.

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

Допустим, у Вас есть хранимая процедура, которая осуществляет перевод средств с одного счета на другой, соответственно, как минимум у Вас будет две операции в этой процедуре, снятие средств, и зачисление средств, например, две инструкции UPDATE.

Но в каждой из этих операций может возникнуть ошибка и инструкция не выполнится. А теперь представьте, что первая инструкция снимает деньги, она выполнилась успешно, вторая инструкция зачисляет деньги и в ней возникла ошибка, без транзакции снятые деньги просто потеряются, так как они никуда не будут зачислены.

Чтобы этого не допустить, все SQL инструкции, которые логически что-то объединяет, в данном случае все операции, связанные с переводом средств, пишут внутри транзакции, и тогда, если наступит подобная ситуация, все изменения будут отменены, т.е. деньги вернутся обратно на счет.

Транзакции можно сочетать с обработкой и перехватом ошибок TRY…CATCH, иными словами, Вы отслеживаете ошибки в Вашем блоке инструкций и если они появляются, то в блоке CATCH Вы откатываете транзакцию, т.е. отменяете все изменения, которые были успешно выполнены до возникновения ошибки в транзакции.

Транзакции – это отличный механизм обеспечения целостности данных.

Свойства транзакции

У транзакции есть 4 очень важных свойства:

  • Атомарность – все команды в транзакции либо полностью выполняются, и соответственно, фиксируются все изменения данных, либо ничего не выполняется и ничего не фиксируется;
  • Согласованность – данные, в случае успешного выполнения транзакции, должны соблюдать все установленные правила в части различных ограничений, первичных и внешних ключей, определенных в базе данных;
  • Изоляция – механизм предоставления доступа к данным. Транзакция изолирует данные, с которыми она работает, для того чтобы другие транзакции получали только согласованные данные;
  • Надежность – все внесенные изменения фиксируются в журнале транзакций и данные считаются надежными, если транзакция была успешно завершена. В случае сбоя SQL Server сверяет данные, записанные в базе данных, с журналом транзакций, если есть успешно завершенные транзакции, которые не закончили процесс записи всех изменений в базу данных, они будут выполнены повторно. Все действия, выполненные не подтвержденными транзакциями, отменяются.

Advanced SQL error handling

We only briefly mentioned tricky part with transactions, so here’s a simple example of how to deal with them. We can use the same procedure as before, only this time let’s wrap a transaction around the Insert statement:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

ALTERPROCEDUREdbo.AddSale@employeeidINT,

@productidINT,

@quantitySMALLINT,

@saleidUNIQUEIDENTIFIEROUTPUT

AS

SET@saleid=NEWID()

BEGINTRY

BEGINTRANSACTION

INSERTINTOSales.Sales

SELECT

@saleid,

@productid,

@employeeid,

@quantity

COMMITTRANSACTION

ENDTRY

BEGINCATCH

INSERTINTOdbo.DB_Errors

VALUES

(SUSER_SNAME(),

ERROR_NUMBER(),

ERROR_STATE(),

ERROR_SEVERITY(),

ERROR_LINE(),

ERROR_PROCEDURE(),

ERROR_MESSAGE(),

GETDATE());

 
— Transaction uncommittable

IF(XACT_STATE())=-1

ROLLBACKTRANSACTION

 
— Transaction committable

IF(XACT_STATE())=1

COMMITTRANSACTION

ENDCATCH

GO

So, if everything executes successfully inside the Begin transaction, it will insert a record into Sales, and then it will commit it. But if something goes wrong before the commit takes place and it transfers control down to our Catch – the question is: How do we know if we commit or rollback the whole thing?

If the error isn’t serious, and it is in the committable state, we can still commit the transaction. But if something went wrong and is in an uncommittable state, then we can roll back the transaction. This can be done by simply running and analyzing the XACT_STATE function that reports transaction state.

This function returns one of the following three values:

  1 – the transaction is committable

-1 – the transaction is uncommittable and should be rolled back

  0 – there are no pending transactions

The only catch here is to remember to actually do this inside the catch statement because you don’t want to start transactions and then not commit or roll them back:

How, if we execute the same stored procedure providing e.g. invalid EmployeeID we’ll get the same errors as before generated inside out table:

The way we can tell that this wasn’t inserted is by executing a simple Select query, selecting everything from the Sales table where EmployeeID is 20:

Как создать свой тип Exception

В Python можно создавать свои исключения. При этом есть одно обязательное условие: они должны быть потомками класса

С помощью контролируются и обрабатываются ошибки в приложении. Это особенно актуально для критически важных частей программы, где любые «падения» недопустимы (или могут привести к негативным последствиям). Например, если программа работает как «демон», падение приведет к полной остановке её работы. Или, например, при временном сбое соединения с базой данных, программа также прервёт своё выполнение (хотя можно было отловить ошибку и попробовать соединиться в БД заново).

Вместе с можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:

Подробнее о работе с исключениями в Python можно ознакомиться в официальной документации.

Конструкция try-catch

Конструкция имеет следующий
синтаксис:

В блоке следует размещать код,
который может содержать исключение. Если
вдруг при выполнении этого кода возникнет
исключительная ситуация, то наш скрипт не
рухнет с ошибкой в консоли, а начнет выполнятся
код блока .

В этом блоке мы должны каким-то адекватным
образом отреагировать на ошибку. Например,
если мы хотели отправить какие-то данные
через интернет и интернет не работает, в
блоке мы можем как-то справится
с ситуацией: можно, например, выдать сообщение
пользователю, а можно через некоторое время
попытаться отправить сообщение опять — вдруг
интернет уже заработал.

Если же при выполнении блока никаких
исключительных ситуаций не случилось, то
полезный код просто выполнится, а код из
блока — нет.

Для примера давайте попробуем разобрать JSON
и в случае его некорректности выведем на
экран сообщение об этом:

Дан код, который записывает некоторую строку
в локальное хранилище:

Оберните этот код в конструкцию .
В блоке выведите сообщение о
переполнении хранилища. Проверьте работу
вашего кода для строки размером менее
мб и для строки большего размера.

Дан JSON, внутри которого хранится массив.
Если этот JSON корректный, то выведите элементы
массива в виде списка . Если же
JSON не корректный, выведите на экран сообщение
о том, что на странице случилась ошибка.

Использование «try…catch»

Давайте рассмотрим реальные случаи использования .

Как мы уже знаем, JavaScript поддерживает метод JSON.parse(str) для чтения JSON.

Обычно он используется для декодирования данных, полученных по сети, от сервера или из другого источника.

Мы получаем их и вызываем вот так:

Вы можете найти более детальную информацию о JSON в главе Формат JSON, метод toJSON.

Если некорректен, генерирует ошибку, то есть скрипт «падает».

Устроит ли нас такое поведение? Конечно нет!

Получается, что если вдруг что-то не так с данными, то посетитель никогда (если, конечно, не откроет консоль) об этом не узнает. А люди очень не любят, когда что-то «просто падает» без всякого сообщения об ошибке.

Давайте используем для обработки ошибки:

Здесь мы используем блок только для вывода сообщения, но мы также можем сделать гораздо больше: отправить новый сетевой запрос, предложить посетителю альтернативный способ, отослать информацию об ошибке на сервер для логирования, … Всё лучше, чем просто «падение».

Archives

  • June 2011 (1)
  • April 2011 (1)
  • January 2011 (1)
  • December 2010 (1)
  • November 2010 (1)
  • October 2010 (1)
  • September 2010 (1)
  • August 2010 (1)
  • July 2010 (1)
  • June 2010 (2)
  • May 2010 (2)
  • April 2010 (3)
  • March 2010 (2)
  • February 2010 (2)
  • January 2010 (2)
  • December 2009 (2)
  • November 2009 (3)
  • October 2009 (3)
  • September 2009 (1)
  • August 2009 (6)
  • July 2009 (4)
  • June 2009 (6)
  • May 2009 (3)
  • April 2009 (2)
  • March 2009 (1)
  • February 2009 (3)
  • January 2009 (6)
  • December 2008 (3)
  • November 2008 (3)
  • October 2008 (2)
  • September 2008 (2)
  • August 2008 (3)
  • July 2008 (3)
  • January 2006 (1)
  • March 2005 (2)
  • February 2005 (3)
  • January 2005 (1)
  • December 2004 (6)

TRY CATCH – Exception Handling in SQL Server

June 16, 2010

Similar to C++, Java and other languages SQL Server also has a mechanism to handle exceptions by using TRY-CATCH construct. The TRY block contains the SQL statements that may raise an error and CATCH block contains the handling mechanism to process the error. When any error is raised in the TRY block the control is immediately transferred to the CATCH block, where the Error is handled.

–> Following rules should be taken care off while using TRY-CATCH constructs:
– A TRY block must be followed immediately by the CATCH block.
– Both TRY & CATCH blocks must be inside a Batch, Stored Procedure or a Trigger.
– Only Errors with severity between 10 & 20 that do not close the database connection are caught & handled by TRY-CATCH constructs.

– As per MS BOL, Errors that have a severity of 20 or higher that cause the Database Engine to close the connection will not be handled by the TRY…CATCH block. And Errors that have a severity of 10 or lower are considered warnings or informational messages, and are not handled by TRY…CATCH blocks.

–> let’s check how to use TRY-CATCH block:

USE 
GO

--// Create a test Stored Procedure
CREATE PROC testPrc (@val VARCHAR(10))
AS
BEGIN
 SELECT 1/@val AS operation
END
GO

--// Test for Divide by 0 (Divide by zero error encountered.)
BEGIN TRY
 EXEC testPrc '0'
END TRY
BEGIN CATCH
 SELECT
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
END CATCH
GO

--// Test for Datatype conversion (Conversion failed when converting the varchar value 'a' to data type int.)
BEGIN TRY
 EXEC testPrc 'a'
END TRY
BEGIN CATCH
 SELECT
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
END CATCH
GO

--// Test nested TRY-CATCH for &quot;Divide by 0&quot; &amp; &quot;Datatype conversion&quot; errors both.
BEGIN TRY
 EXEC testPrc 'a'
END TRY
BEGIN CATCH
 SELECT 'outer block',
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE

 BEGIN TRY
 SELECT 1/0 AS operation
 END TRY
 BEGIN CATCH
 SELECT 'inner block',
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
 END CATCH

END CATCH
GO

--// Test for violation of PK Constraint (Violation of PRIMARY KEY constraint 'PK__testTable__2C3393D0'. Cannot insert duplicate key in object 'dbo.testTable'.)
BEGIN TRY
 CREATE TABLE testTable (a INT PRIMARY KEY)

 INSERT INTO testTable VALUES(1)
 INSERT INTO testTable VALUES(1)
END TRY
BEGIN CATCH
 SELECT
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
END CATCH
GO

SELECT * FROM testTable -- Contains single record with value 1

--// Test for recreating a table that already exists (There is already an object named 'testTable' in the databASe.)
BEGIN TRY
 CREATE TABLE testTable (a INT PRIMARY KEY)
END TRY
BEGIN CATCH
 SELECT
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
END CATCH
GO

--// Test for inserting NULL value on Primary Key column (Cannot insert the value NULL into column 'a', table 'tempdb.dbo.testTable'; column does not allow nulls. INSERT fails.)
BEGIN TRY
 INSERT INTO testTable VALUES(NULL)
END TRY
BEGIN CATCH
 SELECT
 ERROR_NUMBER() AS ERROR_ID,
 ERROR_MESSAGE() AS ERROR_MSG,
 ERROR_SEVERITY() AS ERROR_SEVERITY,
 ERROR_STATE() AS ERROR_STATE,
 ERROR_PROCEDURE() AS ERROR_PROCEDURE,
 ERROR_LINE() AS ERROR_LINE
END CATCH
GO

--// Final Cleanup
DROP TABLE     testTable
DROP PROC testPrc
GO

MS BOL Links for TRY-CATCH: http://msdn.microsoft.com/en-us/library/ms175976.aspxhttp://msdn.microsoft.com/en-us/library/ms179296%28v=SQL.90%29.aspxhttp://msdn.microsoft.com/en-us/library/ms179495.aspx (Error Information)

Advertisement

Categories: DB Concepts
Exception Handling, TRY-CATCH

Исключения обрабатываются немедленно

Вот небольшая программа, демонстрирующая, как исключения обрабатываются немедленно:

Эта программа проста настолько, насколько это возможно. Вот что происходит: инструкция , первая выполняемая инструкция, вызывает исключение типа . Выполнение немедленно переходит к ближайшему охватывающему ее блоку , который является единственным блоком в этой программе. Затем на совпадение проверяются обработчики . Наше исключение относится к типу , поэтому мы ищем обработчик типа . У нас есть один такой, поэтому он и выполняется.

Следовательно, результат этой программы будет следующим:

Обратите внимание, что «This never prints» никогда не печатается, потому что исключение привело к немедленному переходу порядка выполнения к обработчику исключения для значений

try…catch…finally

Подождите, это ещё не всё.

Конструкция может содержать ещё одну секцию: .

Если секция есть, то она выполняется в любом случае:

  • после , если не было ошибок,
  • после , если ошибки были.

Расширенный синтаксис выглядит следующим образом:

Попробуйте запустить такой код:

У кода есть два пути выполнения:

  1. Если вы ответите на вопрос «Сгенерировать ошибку?» утвердительно, то .
  2. Если ответите отрицательно, то .

Секцию часто используют, когда мы начали что-то делать и хотим завершить это вне зависимости от того, будет ошибка или нет.

Например, мы хотим измерить время, которое занимает функция чисел Фибоначчи . Естественно, мы можем начать измерения до того, как функция начнёт выполняться и закончить после. Но что делать, если при вызове функции возникла ошибка? В частности, реализация в коде ниже возвращает ошибку для отрицательных и для нецелых чисел.

Секция отлично подходит для завершения измерений несмотря ни на что.

Здесь гарантирует, что время будет измерено корректно в обеих ситуациях – и в случае успешного завершения и в случае ошибки:

Вы можете это проверить, запустив этот код и введя в – код завершится нормально, выполнится после . А затем введите – незамедлительно произойдёт ошибка, выполнение займёт . Оба измерения выполняются корректно.

Другими словами, неважно как завершилась функция: через или. Секция срабатывает в обоих случаях

Переменные внутри локальны

Обратите внимание, что переменные и в коде выше объявлены до. Если переменную объявить в блоке, например, в , то она не будет доступна после него

Если переменную объявить в блоке, например, в , то она не будет доступна после него.

и

Блок срабатывает при любом выходе из , в том числе и .

В примере ниже из происходит , но получает управление до того, как контроль возвращается во внешний код.

Конструкция без секции также полезна. Мы применяем её, когда не хотим здесь обрабатывать ошибки (пусть выпадут), но хотим быть уверены, что начатые процессы завершились.

В приведённом выше коде ошибка всегда выпадает наружу, потому что тут нет блока . Но отрабатывает до того, как поток управления выйдет из функции.

Errors Unaffected by a TRY…CATCH Construct

TRY…CATCH constructs do not trap the following conditions:

  • Warnings or informational messages that have a severity of 10 or lower.

  • Errors that have a severity of 20 or higher that stop the SQL Server Database Engine task processing for the session. If an error occurs that has severity of 20 or higher and the database connection is not disrupted, TRY…CATCH will handle the error.

  • Attentions, such as client-interrupt requests or broken client connections.

  • When the session is ended by a system administrator by using the KILL statement.

The following types of errors are not handled by a CATCH block when they occur at the same level of execution as the TRY…CATCH construct:

  • Compile errors, such as syntax errors, that prevent a batch from running.

  • Errors that occur during statement-level recompilation, such as object name resolution errors that occur after compilation because of deferred name resolution.

  • Object name resolution errors

These errors are returned to the level that ran the batch, stored procedure, or trigger.

If an error occurs during compilation or statement-level recompilation at a lower execution level (for example, when executing sp_executesql or a user-defined stored procedure) inside the TRY block, the error occurs at a lower level than the TRY…CATCH construct and will be handled by the associated CATCH block.

The following example shows how an object name resolution error generated by a statement is not caught by the construct, but is caught by the block when the same statement is executed inside a stored procedure.

The error is not caught and control passes out of the construct to the next higher level.

Running the statement inside a stored procedure will cause the error to occur at a level lower than the block. The error will be handled by the construct.

Error handling overview

Error handling in SQL Server gives us control over the Transact-SQL code. For example, when things go wrong, we get a chance to do something about it and possibly make it right again. SQL Server error handling can be as simple as just logging that something happened, or it could be us trying to fix an error. It can even be translating the error in SQL language because we all know how technical SQL Server error messages could get making no sense and hard to understand. Luckily, we have a chance to translate those messages into something more meaningful to pass on to the users, developers, etc.

In this article, we’ll take a closer look at the TRY… CATCH statement: the syntax, how it looks, how it works and what can be done when an error occurs. Furthermore, the method will be explained in a SQL Server case using a group of T-SQL statements/blocks, which is basically SQL Server way of handling errors. This is a very simple yet structured way of doing it and once you get the hang of it, it can be quite helpful in many cases.

On top of that, there is a RAISERROR function that can be used to generate our own custom error messages which is a great way to translate confusing error messages into something a little bit more meaningful that people would understand.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Вадлейд
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: