SQL Server 如何处理不同类型的错误?

How does SQL Server handle different type of errors?

提问人:KnowledgeSeeeker 提问时间:7/8/2023 最后编辑:Dale KKnowledgeSeeeker 更新时间:7/9/2023 访问量:80

问:

请找到以下示例代码

    drop table  if exists #myTest
    create table #myTest (
        id int,
        name varchar(30)
    )    
    
    insert into #myTest values
        (1, 'John'),
        (2, 'Somu')
    
    --select 1/0                  -- Query 1 throws error
    --select cast('ABC' as int)   -- Query 2 throws error
    
    insert into #myTest values
        (3, 'Bela'),
        (2, 'Steve')
    
    select * from #myTest

当我取消注释“查询 1”时,它会抛出以下错误,但成功插入了所有 4 行。

消息 8134,级别 16,状态 1,第 62 行 除以遇到的零错误。

当我取消注释“查询 2”时,它会抛出以下错误,但这次没有插入任何行。

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

查看错误消息,不清楚为什么一个错误允许插入行,而第二个错误不允许。有人可以解释一下两者之间有什么区别吗?

sql-server t-sql sqltransaction

评论

6赞 Stu 7/8/2023
这是默认的 off;并非 SQL Server 中的每个错误都足够高,足以中止批处理执行。如果你尝试(这总是一个好主意),你会发现两个错误的行为是一样的。xact_abortset xact_abort on
4赞 siggemannen 7/8/2023
众所周知,Sql Server 在错误处理方面参差不齐。设置 XACT ABORT ON、事务和 TRY CATCH 通常是最理智的处理方式。
8赞 David Browne - Microsoft 7/8/2023
阅读此内容了解血腥细节:sommarskog.se/error_handling/Part1.html
1赞 George Menoutis 7/8/2023
@David Browne对此深表赞同。我最喜欢的部分是 sommarskog.se/error_handling/Part2.html#classification 中的表格
0赞 Charlieface 7/9/2023
在脚本的顶部执行可以使一切更具可预测性。SET XACT_ABORT ON

答:

0赞 Charlieface 7/9/2023 #1

SQL Server 中有两个主要类别的错误:批处理中止和语句中止(还有其他类,但它们通常不相关)。

正如您所观察到的,语句中止错误的行为相当奇怪:只要没有阻塞,它们就会终止整个语句,但会继续到下一行。实际上,每条这样的行都表现得像这样BEGIN CATCH

SAVE TRAN save1;

BEGIN TRY
    -- do the statement here
END TRY
BEGIN CATCH
    ROLLBACK TRAN save1;
END CATCH;

批处理中止错误要明显得多,它们只是中止整个批处理,同时回滚事务。


话虽如此,强烈建议您始终运行 with,因为这会将语句中止错误升级为批处理中止错误,并且通常使错误处理更加合理。SET XACT_ABORT ON;

您可以使用以下命令为所有连接设置它ON

DECLARE @opts int;
SELECT @opts = CAST(value AS int) | 16384  -- bitwise OR the value for XACT_ABORT
FROM sys.configurations
WHERE name = 'user options'

EXEC sp_configure N'user options', @opts;
GO
RECONFIGURE

另请参阅本系列文章,了解有关 SQL Server 特殊错误处理的更多详细信息。