【发布时间】:2014-10-23 17:55:23
【问题描述】:
使用xact_abort ON时如何保存/检索错误状态或返回实际错误?
目前,当我执行这个存储过程时,外部事务已经启动。
begin tran
exec TestFK 2
我得到这个隐藏实际错误的通用错误
当前事务无法提交,也无法支持写入日志文件的操作。回滚事务。
但是当我在没有外部事务的情况下执行时
exec TestFK 2
我得到了正确的错误。
INSERT 语句与 FOREIGN KEY 约束“FK__t2__a__3B783965”冲突。冲突发生在数据库“XXX”、表“dbo.t1”、列“a”中。
ALTER procedure [dbo].[TestFK]
@Id int
as
begin
SET NOCOUNT ON
SET xact_abort ON
DECLARE @trancount INT
SET @trancount = @@TRANCOUNT
begin try
IF @trancount = 0
BEGIN TRANSACTION
INSERT INTO t2 VALUES (@Id); -- Foreign key error for @Id = 2
IF @trancount = 0
COMMIT TRANSACTION
end try
begin catch
IF Xact_state() <> 0 AND @trancount = 0
ROLLBACK TRANSACTION
Exec uspInsErrorInfo -- Here I want to preserve the Error State somehow
end catch
END
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
CREATE TABLE t2 (a INT NOT NULL REFERENCES t1(a));
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4);
INSERT INTO t1 VALUES (6);
【问题讨论】:
-
呃,
IF @trancount = 0 / COMMIT?为什么你关心(并且正在根据)@@TRANCOUNT在BEGIN TRANSACTION之前是什么? -
如果
@trancount <> 0则表示事务是在存储过程之外发起的,调用者将负责提交事务 -
这不是
@@NESTLEVEL的用途吗?你也知道在 SQL Server 中并没有像嵌套事务这样的东西,对吧?您是否仔细阅读了 Erland 的文章?从这里开始:sommarskog.se/error_handling_2005.html -
实际上 SP 是从
C#代码调用的,它做了两件事 1. 调用这个 SP 2. 更新SOLR。我们需要应用程序级别的事务,以便如果SOLR更新失败,SP 可以回滚。这个SP也是独立调用的,所以我们也需要SP中的事务。 -
一种更简单的方法是在以一种方式与另一种方式调用过程时传递参数。
标签: sql sql-server transactions sql-server-2012 try-catch