sql-server - 为什么在引发除以零异常后执行插入语句
问题描述
我有以下查询。
IF Object_id('tempdb..#test_tran') IS NOT NULL
DROP TABLE #test_tran
CREATE TABLE #test_tran
(
id INT,
name VARCHAR(255)
)
GO
----------------------------------------
BEGIN TRAN
DECLARE @a FLOAT = 1 / 0.0
INSERT INTO #test_tran VALUES (1, 'Red')
COMMIT TRAN
----------------------------------------
GO
SELECT * FROM #test_tran
输出是
Msg 8134, Level 16, State 1, Line 17
Divide by zero error encountered.
(1 row affected)
(1 row affected)
Completion time: 2020-07-12T12:39:16.9097805+03:00
为什么在 DECLARE @a FLOAT = 1 / 0.0 发生错误时事务没有停止?为什么在引发除以零异常后执行插入语句?
如果我使用 BEGIN TRY BEGIN CATCH 异常被捕获并阻止插入,但我想了解为什么在抛出异常后继续执行。
解决方案
SQL 异常的行为方式与它们在应用程序代码中的行为方式不同。它们并不总是导致堆栈展开到一个 catch 块(或进程终止)——除非你实际上有一个 catch 块。
在 SQL 中,一些错误会导致整个批处理终止,而其他错误可能不会 - 取决于xact_abort
. 关于这方面的一些信息可以在 的备注中找到raiserror
。
如果错误severity
大于 10,并且错误不在块中try
,则客户端应用程序将接收该错误作为异常的一部分。
如果错误severity
大于 20,则整个批处理 - 以及连接 - 将终止。
因此,有三种方法可以“检测” TSQL 中的错误:
- 使用 try/catch
@@error
在每条语句之后检查系统变量的值。- 如果你总是想停止处理,那么
set xact_abort on
推荐阅读
- java - 从 URI 到 JDBC 端点的 Camel CXF - org.apache.cxf.binding.soap.SoapFault
- bulma - 对齐 Buefy 下拉菜单以避免切边
- php - 从显示类型为 Woocommerce 子类别的产品类别中删除侧边栏
- c++ - 为什么查找使用数组元素形成的最大数的程序不起作用?
- python - 返回列表的第一个数字
- php - 更新表列并将旧数据推送到另一列
- php - 将数组组合到第 n 次
- java - 在 Jtable Java 中创建活动单元格获取值?
- javascript - 管理过滤器 ID Gmail
- node.js - 在执行 npm install 时出现“没有打开这样的文件或目录”的错误