2016-06-14 263 views
3

如果我跑了以下內容:奇怪的行爲

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); 
GO 

之後,我運行此:

SET XACT_ABORT ON; 

BEGIN TRANSACTION 
INSERT INTO t2 VALUES (1) 

INSERT INTO t2 VALUES (2) -- Foreign key error, entire transaction rolled back 

INSERT INTO t2 VALUES (3) 

COMMIT TRANSACTION 

那麼什麼是確定的;該交易回滾,因爲我們在t1中沒有值2,並且因此表t2爲空

但是,如果我在此交易中添加GO命令,那麼事務不會回滾到第3位被插入到表格t2中。下面是代碼:

SET XACT_ABORT ON; 

BEGIN TRANSACTION 
INSERT INTO t2 VALUES (1) 

INSERT INTO t2 VALUES (2) -- Foreign key error. 

GO --this command breaks the transaction 

INSERT INTO t2 VALUES (3) 

COMMIT TRANSACTION 

我知道GO不是SQL語句,但實際未發送到SQL服務器,而一個SQL Server Management Studio中實用程序命令。

那麼,爲什麼上面跑(包括GO命令的)最後的代碼片斷後,我可以看到表t2 3號

我使用SQL Server Management Studio中

+1

這絕對符合預期的行爲。這可能是你對'GO'如何工作的誤解。請參閱https://msdn.microsoft.com/en-us/library/ms188037.aspx?f=255&MSPPError=-2147217396以瞭解更多有關'批次'的信息。 – techspider

+2

Point:'GO' does not *** not *** break交易。事務是會話級別的工件,而不是批次級別。 SSMS中的「GO」打破了一個批次,而不是一個會話。 – RBarryYoung

回答

8

SET XACT_ABORTON ,如果一個Transact-SQL語句產生一個 運行時錯誤,則整個事務終止並回滾。

首批打開該交易確實得到自動回滾上的錯誤。

然後SSMS看到還有另一批來處理和火災關閉

INSERT INTO t2 VALUES (3) 

COMMIT TRANSACTION 

隨着第一筆交易已經結束這將啓動一個新的自動提交事務。最後還有一個意想不到的COMMIT TRANSACTION,所以會產生錯誤。

您可以更改第二批以檢查第一批中的事務是否被毫不客氣地回滾。

SET XACT_ABORT ON; 

BEGIN TRANSACTION 
INSERT INTO t2 VALUES (1) 

INSERT INTO t2 VALUES (2) -- Foreign key error. 

GO 

IF @@TRANCOUNT = 0 
    BEGIN 
    RAISERROR('Transaction closed',16,1); 
    RETURN; 
    END 

INSERT INTO t2 VALUES (3) 

COMMIT TRANSACTION 

或者你可以打開SQLCMD模式,並使用

:on error exit 

如果你想不再批錯誤後進行處理。

enter image description here

+0

我與這個答案一致,但是OP說他可以在GO之後看到'2'而不是回滾;我很困惑OP是否確定這個問題,儘管:) – techspider

+4

一如既往的Spot。 – RBarryYoung

+0

是的,我可以在表格t2中看到數字2。這是問題。您可以複製代碼/粘貼代碼並嘗試。 – Christian