不能用@@ERROR或XACT_STATE获取“上一个事务”状态,二者仅反映最近语句或当前事务的瞬时状态;事务结束后其值即失效或重置,无历史记录能力,需通过日志表等外部机制持久化记录。

不能用 @@ERROR 或 XACT_STATE 获取“上一个事务”的状态,它们只反映“最近一次语句”或“当前事务”的即时状态。 试图靠它们回溯已结束事务的成败,属于典型误用——这两个值在事务提交/回滚后即失效或重置,没有历史记录能力。
@@ERROR 只捕获紧邻前一条语句的错误号
它不是事务级状态变量,而是每执行完一条语句就立即覆盖的“瞬时快照”。即使你在 BEGIN TRY 外写 SELECT @@ERROR,拿到的也只是那条 SELECT 自身是否出错(通常为 0),和之前事务毫无关系。
- 执行
INSERT报错 →@@ERROR返回非 0 错误号 - 紧接着执行
SELECT 1→@@ERROR立即变成 0,无论前面 INSERT 是否成功 - 事务已
COMMIT或ROLLBACK后再查@@ERROR,结果恒为 0
XACT_STATE() 返回的是当前会话的事务活性,不是历史记录
XACT_STATE() 的返回值(-1/0/1)只说明“此刻”事务所处的逻辑状态:-1 表示不可提交的异常事务(如死锁被选为牺牲品)、0 表示无活动事务、1 表示可提交的活跃事务。它不保存、也不提供任何关于“上一个事务是否成功”的信息。
- 事务 A 执行完并
COMMIT→ 当前无事务 →XACT_STATE()返回0 - 事务 B 随后启动 →
XACT_STATE()变成1,但完全不知道事务 A 的结局 - 若事务 B 中发生严重错误(如违反约束),
XACT_STATE()可能变为-1,但这和事务 A 无关
真想查“上一个事务”状态?得靠外部持久化记录
SQL Server 本身不维护事务执行结果的历史日志供 T-SQL 直接查询。要实现类似需求,必须主动设计记录机制:
- 在关键事务块末尾,显式把
@@ERROR、GETDATE()、@@TRANCOUNT和业务上下文写入一张日志表(如TransactionLog) - 用
TRY...CATCH捕获异常,并在CATCH块中统一记录失败详情,避免依赖事后查@@ERROR - 不要轮询
sys.dm_exec_requests查“刚结束的事务”,它只显示status = 'running'等实时状态,已结束的请求不会停留其中
真正容易被忽略的一点:很多人以为 @@ERROR 能当“事务执行摘要”用,其实它连单条语句的完整错误信息(比如消息文本、严重级别)都不包含——这些必须靠 ERROR_MESSAGE()、ERROR_SEVERITY() 在 CATCH 块里取。离开 TRY...CATCH 范围谈“上一个事务状态”,本质上是在查一个已被擦除的内存值。










