2016-04-18 21 views
7

這是我stored procedure執行流程:插入在事務內失敗,但sql服務器返回1行受影響?

ALTER procedure dbo.usp_DoSomething 

as 

declare @Var1 int 
declare @Var2 int 
declare @Var3 int 

select 
@Var1 = Var1, 
@Var2 = Var2, 
@Var3 = Var3 
from Table 
where 
... 

BEGIN TRY 
    BEGIN TRANSACTION 
     /* UPDATE Table. This executes successfully */ 

     /* INSERT Table. This fails due to PK violation */ 

     COMMIT TRAN /* This does not happen */ 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRAN /* This occurs because TRANS failed */ 
END CATCH 

UPDATE運行成功。 INSERT失敗,所以transaction回滾。

執行後,表看起來是正確的,沒有什麼改變。但是,當我運行SP,我得到了以下信息:

(1 row(s) affected) 

(0 row(s) affected) 

所以我問自己,哪裏是第一1 row(s) affected是從哪裏來的?

然後我在想,這是什麼原因,但希望確認:OUTPUT Clause (Transact-SQL)

An UPDATE, INSERT, or DELETE statement that has an OUTPUT clause will return 
rows to the client even if the statement encounters errors and is rolled back. 
The result should not be used if any error occurs when you run the statement. 
+0

是的,就是這樣。 – Quassnoi

+0

但爲什麼不報告'INSERT'的錯誤?相反,它表示「0行受影響」。這有點誤導人。 – rbhat

+1

你在這裏有一個反模式,我稱之爲嘗試壓制。你遇到了捕捉異常的麻煩,但是你只是繼續進行,就好像什麼都沒有發生。這種類型的東西難以調試。回滾是好的,但你需要重新拋出你的異常,所以你知道它發生了,並有一些想法發生了什麼錯誤。 –

回答

1

默認情況下,行數將是每一個DML語句,除非SET NOCOUNT ON啓用返回。無論事務是否成功,或者回滾或提交,您的UPDATE語句都是成功的,因此通知(1 row(s) affected)

您提到的OUTPUT子句與它無關,因爲您沒有指定它。

+0

我似乎不明白的是,爲什麼返回消息從紅色'消息2601 - 使用'TRANS'在'object'中不能插入重複鍵行'到'0 rows(s)affected'。 – rbhat

+0

或者至少'0 rows(s)affected',然後是一個消息說'ROLLBACK'發生了。 – rbhat

+0

更新語句創建了「受影響的1行」,失敗的插入語句創建了「受影響的0行」。 – Greg

0

第一次選擇設置變量可能會產生1行受影響

+0

它沒有。我用那個'SELECT'創建了SP。當我運行它時,我得到了'Command(s)completed successfully.'。 – rbhat

+0

是的你是對的,@Greg答案是正確的 –