SQL Server两类错误为何引发不同插入结果?求技术解析
问题:SQL Server两类错误导致不同插入结果的差异解析
测试代码
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 触发错误 --select cast('ABC' as int) -- Query 2 触发错误 insert into #myTest values (3, 'Bela'), (2, 'Steve') select * from #myTest
报错与执行结果
取消注释Query1(执行select 1/0)
Msg 8134, Level 16, State 1, Line 62
Divide by zero error encountered.
此时成功插入全部4行数据。
取消注释Query2(执行select cast('ABC' as int))
Msg 245, Level 16, State 1, Line 63
Conversion failed when converting the varchar value 'ABC' to data type int.
此时未插入任何行数据。
疑问:两类错误的级别均为16,为何导致完全不同的插入结果?
解析
核心原因是SQL Server对这两类错误的批处理终止范围和事务行为存在本质区别:
1. 除零错误(Msg 8134):语句级终止错误
这类错误属于非致命的语句级错误,仅会中断当前执行的select 1/0语句,不会影响批处理中其他独立语句的执行:
- 第一个
insert语句在错误发生前已执行完成,默认单个语句为隐式事务,执行后立即提交,因此前两行数据已存入表中。 - 错误触发后,批处理并未终止,第二个
insert语句会继续执行并提交,最终表中存在全部4行数据。
2. 类型转换错误(Msg 245):批处理级终止错误
这类错误属于会触发批处理中止的致命错误,具体行为分两种场景:
场景一:默认SET XACT_ABORT OFF(系统默认配置)
- 第一个
insert语句会正常执行并提交,表中会存在前两行数据;错误发生后,批处理中止,第二个insert语句不会执行。 - 若测试时未看到前两行,可能是操作误判或环境存在特殊配置。
场景二:SET XACT_ABORT ON
- 当该配置开启时,任何级别≥16的错误都会立即终止批处理,并回滚所有未提交的事务(包括之前已执行的语句)。此时整个批处理的所有操作都会被回滚,表中无任何数据,与你描述的结果一致。
额外补充:cast('ABC' as int)属于运行时错误,但在某些特殊场景(如涉及变量的强制转换)可能触发编译阶段错误,此时整个批处理会直接停止,不会执行任何语句,也会导致表中无数据。
内容的提问来源于stack exchange,提问作者KnowledgeSeeeker
相关产品推荐
相关产品推荐

