2016-04-18 12 views
7

Questo è il flusso di esecuzione del mio stored procedure:L'inserimento non riesce nella transazione, ma SQL Server restituisce 1 riga/e interessata?

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 

I UPDATE viene eseguito correttamente. INSERT non riesce, quindi viene eseguito il rollback dello transaction.

Dopo l'esecuzione, la tabella sembra corretta e nulla è cambiato. Ma quando ho eseguito la SP, ottengo i seguenti messaggi:

(1 row(s) affected) 

(0 row(s) affected) 

Quindi mi chiedo, dove si trova il primo 1 row(s) affected provenienti da?

Poi mi viene da pensare che questa è la ragione, ma ha voluto confermare: 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

sì, è tutto. – Quassnoi

+0

Ma perché non segnalare l'errore per l''INSERTO'? Invece dice '0 row (s) affected'. È una sorta di fuorviante. – rbhat

+1

Qui c'è un anti-pattern che chiamo try-squelch. Ti sei preso la briga di prendere un'eccezione, ma poi continui come se nulla fosse accaduto. Questo tipo di cose è incredibilmente difficile da eseguire il debug. Il rollback va bene, ma è necessario rilanciare l'eccezione in modo da sapere che succede e avere un'idea di cosa sia successo. –

risposta

1

Per impostazione predefinita, un conteggio delle righe saranno restituiti per ogni dichiarazione DML, a meno che non SET NOCOUNT ON è abilitato. Indipendentemente dal fatto che una transazione abbia esito positivo o meno, o ripristinata o impegnata, l'istruzione UPDATE ha avuto esito positivo, quindi la notifica (1 row(s) affected).

La clausola OUTPUT non ha nulla a che fare con esso, poiché non è stata specificata.

+0

Quello che non sembra capire è il motivo per cui il messaggio di ritorno cambia dal rosso 'Msg 2601 - Impossibile inserire la riga chiave duplicata nell'oggetto' a' 0 riga (s) interessate' con l'uso di 'TRANS'. – rbhat

+0

O almeno, '0 righe (s) interessate 'e poi un messaggio che dice che è stato eseguito un' ROLLBACK'. – rbhat

+0

L'istruzione di aggiornamento ha creato la "riga 1 interessata", l'istruzione di inserimento non riuscita ha creato la "riga 0 interessata". – Greg

0

La prima selezione con le variabili di impostazione potrebbe produrre 1 riga interessata

+0

Non funziona. Ho creato l'SP con solo quel 'SELECT'. Quando lo eseguo, i comandi vengono completati correttamente. – rbhat

+0

Sì, hai ragione e la risposta @Greg è corretta –

Problemi correlati