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


9

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

我想知道的是,是否有明确的列表列出哪些错误正在批处理中止,哪些错误正在语句终止。

Answers:


6

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

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

CATCH块不会处理终止数据库连接的错误(严重程度通常为20到25),因为连接终止时执行将中止。

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

SELECT message_id, severity, [text]
FROM sys.messages
WHERE language_id = 1033 
AND severity >= 19
ORDER BY severity, message_id;

在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

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

消息8146,级别16,状态2,过程pA,第11行
过程pA没有提供参数和参数。
###不使用参数
Msg 201,级别16,状态4,过程pB,行14 的参数的调用过程
过程或函数'pB'期望使用未提供的参数'@x'。
###带有2个参数且没有参数的调用过程
Msg 201,级别16,状态4,过程pB,第18行
过程或函数'pB'期望提供参数'@y',但未提供。
###带有2个参数且参数不足的调用过程
Msg 8144,级别16,状态2,过程pB,第22行
过程或函数pB指定了太多参数。
###带有2个参数且参数过多的调用过程

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

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

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

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


非常感谢你!我认为由于先前的不一致,我将无法使用严重性级别作为指标。很高兴听到事实并非如此。
Jamie Alford

啊!仍有一些严重性级别16错误将中止该批处理。如果我选择并执行:开始tran print @@ TRANCOUNT打印convert(int,'abc'),然后执行:print @@ TRANCOUNT将出现16级错误,但是该批处理将被中止。
Jamie Alford

顺便说一句,如果你发现其中的异常引发从宣布一个不同严重程度的情况下,请通过连接举报他们
莱姆斯Rusanu

2

除了@Aaron指出的错误类型(即,严重性> = 19和转换失败)之外,MSDN页面中针对TRY ... CATCH指出的以下类型的错误也将中止批处理:

当以下错误类型与TRY…CATCH构造在同一执行级别上发生时,CATCH块将不对其进行处理:

  • 编译错误(例如语法错误)会阻止批处理运行。

  • 在语句级重新编译期间发生的错误,例如由于延迟的名称解析而在编译后发生的对象名称解析错误。

这些错误将返回到运行批处理,存储过程或触发器的级别。

在下面的示例中,请注意其中三个甚至是严重级别15。

例1

SET XACT_ABORT OFF;
SELECT @NotDeclared; -- parse error
PRINT 'Do you see me?';

返回值:

消息137,级别15,状态2,第2行
必须声明标量变量“ @NotDeclared”。

例子2

SET XACT_ABORT OFF;
InvalidSQL; -- parse error
PRINT 'Do you see me?';

返回值:

消息102,级别15,状态1,第2行
'InvalidSQL'附近的语法不正确。

实施例3

SET XACT_ABORT OFF;
SELECT 1 -- statement preceding THROW not terminated by semicolon
THROW 50505, N'Error, yo', 1; -- parse error
PRINT 'Do you see me?';

返回值:

消息102,级别15,状态1,第3行
'50505'附近的语法不正确。

实施例4

SET XACT_ABORT OFF;
SELECT NoSuchColumn FROM sys.objects; -- compilation error
PRINT 'Do you see me?';

返回值:

消息207,级别16,状态1,第3行
无效的列名称'NoSuchColumn'。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.