SQL Try поймать цель неясно - PullRequest
1 голос
/ 10 июня 2010

Предположим, я хочу сообщить приложению о том, что произошло / вернул SQL-сервер. Давайте иметь этот блок кода:

BEGIN TRY
    -- Generate divide-by-zero error.
    SELECT 1/0;
END TRY
BEGIN CATCH
     SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() as ErrorState,
        ERROR_PROCEDURE() as ErrorProcedure,
        ERROR_LINE() as ErrorLine,
        ERROR_MESSAGE() as ErrorMessage;
END CATCH;
GO

и давайте иметь этот блок кода:

SELECT 1/0;

Мой вопрос: Оба возвращают деление на ноль ошибок . Чего я не понимаю, так это того, почему я должен окружить его выражением try catch, когда я получил эту ошибку в обоих случаях? Не правда ли, что эта ошибка будет в обоих случаях распространена на клиентское приложение?

Ответы [ 5 ]

3 голосов
/ 10 июня 2010

Да, единственная причина для Try Catch (как в обычном коде) заключается в том, что вы можете «обработать» ошибку, т. Е. Вы можете исправить ошибку и успешно завершить любую функцию, которую выполняла процедура, или Если вы хотите что-то сделать с ошибкой, прежде чем вернуть ее клиенту (например, изменить сообщение или сохранить его в таблице журнала ошибок или отправить кому-то электронное письмо и т. д. (хотя я бы предпочел сделать большинство этих слой DAL)

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

Как вы написали, клиенту не будет возвращено никакой ошибки. Как и в обычном коде, если вы не обрабатываете (исправляете) ошибку в предложении catch, вы всегда должны перебрасывать ее (в sql, что означает функцию Raiserror) в предложении catch. То, что вы сделали выше, в целом плохо, клиентский код может или не может иметь какую-либо возможность правильно справиться с совершенно другой набор записей (один с информацией об ошибке) от того, что он ожидал. Некоторые вызовы (например, вставки обновлений или удалений) могут вообще не ожидать или искать возвращенный набор записей ... Вместо этого, если вы хотите или должны что-то сделать с ошибкой в ​​процедуре перед возвратом ее клиенту, используйте Raiserror() функция

BEGIN TRY 
    -- Generate divide-by-zero error. 
    SELECT 1/0; 
END TRY 
BEGIN CATCH 
     -- Other code to do logging, whatever ... 
     Raiserror(ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_STATE() )
END CATCH; 
1 голос
/ 10 июня 2010

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

Если вы создаете динамический SQl в блоке Try, также полезно регистрировать динамическую переменную SQl, в которой произошел сбой, и любые параметры, переданные.помогите решить некоторые труднодостижимые ошибки: «мы понятия не имеем, что на самом деле сделал пользователь, чтобы вызвать проблему».

1 голос
/ 10 июня 2010

Оба возвращают ошибку деления на ноль.

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

Разница в том, что в первом примере вы ожидаетеошибка и как-то с ней бороться.Ошибка поступает в приложение как обычный результат - она ​​не распространяется через механизм обработки ошибок.На самом деле, если приложение не выглядит конкретно как форма результата, то оно может не знать, что произошла ошибка.

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

Вы выбираете, что имеет смысл для вашего приложения.Может ли приложение осмысленно обработать ошибку - если это так, распространять ошибку (2-й пример) или лучше всего ее обрабатывать в запросе (1-й пример), причем ошибки «сглаживаются» путем возврата результатов по умолчанию, таких как пустой набор строк.

0 голосов
/ 10 июня 2010

Используя первый метод, вы не получите ошибку от SQL Server напрямую

Второй метод может остановить выполнение операторов, следующих за ним

Так что лучше перехватить еезаранее

0 голосов
/ 10 июня 2010

Нет, выполнив Select 1/0 в блоке TRY / CATCH, оператор выбора ничего не возвращает, а оператор выбора в блоке catch изящно отображает подробности ошибки.Запрос завершается успешно - никаких ошибок не выдается.

Если вы запускаете Select 1/0 самостоятельно, запрос не завершается успешно - он взрывается с ошибкой.

Использование блока catch внутриSQL дает вам возможность тут же что-то сделать, а не просто позволить пузырю ошибки доходить до приложения.

Единственная причина, по которой вы видите подробности ошибки, заключается в том, что вы выбираете их.Если бы в блоке Catch не было кода, вы бы не увидели никакой информации об ошибке.

...