SQL Server 中的批处理中止错误列表

Jam*_*ord 10 sql-server transaction error-handling sql-server-2012

在 SQL Server 中,如果 XACT_ABORT 关闭,则某些错误将终止当前语句(例如,向采用某些参数的存储过程提供不正确数量的参数),而某些错误将中止整个批处理(例如,向存储过程提供参数)不带参数的过程)。[参考]:http : //www.sommarskog.se/error-handling-I.html#scope-abortion

我想知道的是是否有一个明确的列表,列出哪些错误是批量中止,哪些是语句终止。

Aar*_*and 7

我相信有一些例外,但来自数据库引擎错误严重性(MSDN)

严重级别为 19 或更高的错误消息会停止执行当前批处理。

终止数据库连接的错误,通常具有 20 到 25 的严重性,不会由 CATCH 块处理,因为在连接终止时执行被中止。

因此,您似乎可以从以下查询中获得一个明确的列表(当然,这不允许您过滤掉哪些可能是由用户 T-SQL 引起的):

SELECT message_id, severity, [text]
FROM sys.messages
WHERE language_id = 1033 
AND severity >= 19
ORDER BY severity, message_id;
Run Code Online (Sandbox Code Playgroud)

在 SQL Server 2012 中,这会生成 210 行。

在 SQL Server 2016 中,这会生成 256 行。

顺便说一句,我不相信您在问题中描述的两种情况按照您的想法工作,至少在现代版本的 SQL Server 中不是这样。我在 2012 年和 2016 年都尝试过这个(我相信 Erland 的文章描述了 SQL Server 2000 的行为,我不记得它是否有任何不同,但即使是这样,今天也不是很相关)。

USE tempdb;
GO

CREATE PROCEDURE dbo.pA -- no parameters
AS PRINT 1
GO
CREATE PROCEDURE dbo.pB -- two parameters
@x INT, @y INT
AS PRINT 1
GO

SET XACT_ABORT OFF;
GO

EXEC dbo.pA @foo = 1; 
PRINT '### Calling procedure that doesn''t take parameters with a parameter';
GO

EXEC dbo.pB; 
PRINT '### Calling procedure that takes 2 parameters with no parameters';
GO

EXEC dbo.pB @x = 1; 
PRINT '### Calling procedure that takes 2 parameters with not enough parameters';
GO

EXEC dbo.pB @x = 1, @y = 2, @z = 3; 
PRINT '### Calling procedure that takes 2 parameters with too many parameters';
GO
Run Code Online (Sandbox Code Playgroud)

这些都会产生严重级别为 16 的错误,并且所有这些错误都会继续进行批处理,如打印输出所示:

消息 8146,级别 16,状态 2,过程 pA,第 11 行
过程 pA 没有参数,并且提供了参数。
### 调用不带参数的过程,带有参数
消息 201,级别 16,状态 4,过程 pB,第 14 行
过程或函数“pB”需要参数“@x”,该参数未提供。
### 调用带有 2 个参数的过程,没有参数
消息 201,级别 16,状态 4,过程 pB,第 18 行
过程或函数“pB”需要参数“@y”,但未提供。
### 2 个参数不足的调用过程
Msg 8144, Level 16, State 2, Procedure pB, Line 22 ### 2 个参数过多的调用过程
过程或函数 pB 指定的参数过多。

正如我所怀疑的那样,当然,正如评论中所指出的那样,也有例外。转换失败的严重性为 16,但会中止批处理:

SET XACT_ABORT OFF;
SELECT CONVERT (INT, 'foo');
PRINT 'Made it.'; -- no print happens
Run Code Online (Sandbox Code Playgroud)

这次的结果不包括打印输出:

消息 245,级别 16,状态 1
将 varchar 值“foo”转换为数据类型 int 时转换失败。