我的存储过程类似于:
CREATE PROCEDURE my_procedure
@val_1 INT,
@val_2 INT
AS
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO table_1(col_1, col_2)
VALUES (@val_1, @val_2);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
DECLARE
@ERROR_SEVERITY INT,
@ERROR_STATE INT,
@ERROR_NUMBER INT,
@ERROR_LINE INT,
@ERROR_MESSAGE NVARCHAR(4000);
SELECT
@ERROR_SEVERITY = ERROR_SEVERITY(),
@ERROR_STATE = ERROR_STATE(),
@ERROR_NUMBER = ERROR_NUMBER(),
@ERROR_LINE = ERROR_LINE(),
@ERROR_MESSAGE = ERROR_MESSAGE();
RAISERROR('Msg %d,
Line %d,
:%s',
@ERROR_SEVERITY,
@ERROR_STATE,
@ERROR_NUMBER,
@ERROR_LINE,
@ERROR_MESSAGE);
END CATCH
当通过数据库执行此代码时,一切都正常运行。通过ADO.NET执行时,我收到以下错误消息:
“INSERT语句与FOREIGN KEY约束”FK_table1_table2
“冲突。冲突发生在数据库”my_database
“,表”dbo.table_1
“,列'col_1
'.EXECUTE后的事务计数表示缺少COMMIT或ROLLBACK TRANSACTION语句。前一个count = 1,当前count = 0.“
是否发生这种情况是因为XACT_ABORT
设置强制回滚来自ADO.NET的事务?避免这个错误的最佳方法是什么?
答案 0 :(得分:2)
您可以在代码中检查XACT_STATE(),然后提交或回滚,请在此处查看:Use XACT_STATE() To Check For Doomed Transactions
基本上这样的事情会爆炸
BEGIN TRANSACTION TranA
BEGIN TRY
DECLARE @cond INT;
SET @cond = 'A';
END TRY
BEGIN CATCH
PRINT 'a'
END CATCH;
COMMIT TRAN TranA
当你检查xact_state时你可以控制它
BEGIN TRANSACTION TranA
BEGIN TRY
DECLARE @cond INT;
SET @cond = 'A';
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH;
IF XACT_STATE() =0
BEGIN
COMMIT TRAN TranA
END
ELSE
BEGIN
ROLLBACK TRAN TranA
END
另外看看这两个必读的链接 Implementing Error Handling with Stored Procedures和Error Handling in SQL Server – a Background。
答案 1 :(得分:2)
如果XACT_STATE()= 0 BEGIN COMMIT TRAN TranA END
会产生错误。 XACT_STATE()= 0表示没有要提交或回滚的事务
XACT_STATE()= 1表示存在可提交的事务
XACT_STATE()= -1表示在当前上下文结束时,数据库引擎将回滚不可交付的事务。