为什么T-SQL不会因错误而停止

时间:2018-05-16 07:58:25

标签: sql-server tsql

如果我执行以下查询

EXEC spFoo
PRINT 'TEST'

spFoo抛出错误,它仍然执行print语句。

但是,如果我这样做

BEGIN TRY
    EXEC cdb.spFoo
    PRINT 'TEST'
END TRY
BEGIN CATCH
    THROW;
END CATCH

它的行为与我预期的一样,并且在发生错误后不会继续。

有人可以帮我解释一下这种行为吗?即使我将其封装在一个事务中,它仍然会继续。它不仅具有印刷声明,还具有任何其他功能。我最初的想法是,这是一个严重性问题,但严重性是16级。这是正常的T-SQL行为吗?如果是这样,那么与我曾经使用过的其他语言相矛盾的这种设计的动机会直接升级错误吗?

我已尝试并在几台不同的计算机上看到SQL Server 2012,2014和2017中的相同行为。有问题的存储过程链接到SQL CLR。​​

3 个答案:

答案 0 :(得分:3)

严重级别为16级是警告级别。用户需要处理任何错误 - 包括定义何时需要终止。

用你的第一个例子:

EXEC spFoo
PRINT 'TEST'

这些是独立的语句,虽然spFoo可能会失败,但服务器将转移到下一个语句。这是因为严重性小于20,批次未自动终止。

用你的第二个例子,

BEGIN TRY
    EXEC cdb.spFoo
    PRINT 'TEST'
END TRY
BEGIN CATCH
    THROW;
END CATCH

您已经拥有决定与相关的内容的所有权。

由于TRY块中的一个项目失败,因此它不会移动到下一个项目。

THROW始终终止批处理

调用THROW后,如果您之后继续执行任何代码,则不会执行此操作。如果这很重要,您可以使用RAISERROR继续。

A detailed explanation of errors

Part 2 of explanations

An answer from the same person

Severity levels

答案 1 :(得分:0)

您应该在此处解释TRY...CATCH

  

TRY ... CATCH构造捕获所有具有的执行错误   严重性高于10且不关闭数据库连接。

在SQL中,TRY..CATCH的工作方式与C#/ VB等的工作方式完全不同,因此基于严重性,它可以正常工作。

如果您需要查看先前语句中是否发生任何错误,请使用@@ERROR

示例,IF @@ERROR <> 0 PRINT 'TEST'

尝试打印@@ ERROR给出的结果。它可能会给你任何暗示。

如果前一个Transact-SQL语句没有遇到任何错误,则返回0.

  

(来自上面的链接)@@ ERROR如果上一个语句遇到错误,则返回错误号   错误。如果错误是sys.messages目录中的错误之一   查看,然后@@ ERROR包含sys.messages.message_id中的值   该错误的列。您可以查看与之关联的文本   sys.messages中的@@ ERROR错误号。

检查是否有来自@@ ERROR

的任何有用信息

答案 2 :(得分:0)

  

TRY .. CATCH

不会停止查询过程。如果您在捕获错误后不想继续,请使用RETURN。这将停止该过程。此外,如果您使用BEGIN TRANSACTION,请在退出流程之前使用ROLLBACK。否则它将以未提交的交易结束。

相关问题