Ho un trigger INSERT su una delle mie tabelle che emette un THROW quando trova un duplicato. Il problema è che le transazioni sembrano essere implicitamente rallentate a questo punto - questo è un problema, voglio controllare quando le transazioni vengono fatte tornare indietro.SQL Server Ripristina la transazione quando si utilizza THROW
Il problema può essere ri-creato con questo script:
CREATE TABLE xTable (
id int identity not null
)
go
create trigger xTrigger on xTable after insert as
print 'inserting...';
throw 1600000, 'blah', 1
go
begin tran
insert into xTable default values
rollback tran
go
drop table xTable
Se si esegue il rollback tran - ti dirà non c'è si cominciano tran.
Se scambio il THROW per un'eccezione "normale" (come SELECT 1/0), la transazione non viene ripristinata.
Ho controllato il flag xact_abort ed è spento.
Utilizzo di SQL Server 2012 e la sperimentazione attraverso SSMS
Qualsiasi aiuto apprezzato, grazie.
EDIT Dopo aver letto gli articoli pubblicati da @ Dan Guzman, sono giunto alla seguente conclusione/sintesi ...
SQL Server imposta automaticamente XACT_ABORT ON nei trigger.
Il mio esempio (sopra) non illustra la mia situazione - In realtà sto creando un vincolo esteso utilizzando un trigger.
Il mio caso d'uso è stato inventato, stavo cercando di testare più situazioni nel test di unità SAME (non una situazione reale, e NON una buona pratica di test unitario).
La mia gestione del controllo esteso del vincolo e il lancio di un errore nel trigger sono corretti, tuttavia non esiste una situazione reale in cui non vorrei effettuare il rollback della transazione.
Può essere utile impostare XACT_ABORT OFF all'interno di un trigger per un caso particolare; ma la tua transazione sarà comunque compromessa da errori generali di interruzione del batch (come deadlock).
Ragioni storiche a parte, non sono d'accordo con la gestione di questo da parte di SQL Server; solo perché non esiste una situazione attuale in cui desideri continuare la transazione, non significa che una situazione del genere non possa sorgere. Mi piacerebbe vedere uno in grado di configurare SQL Server per mantenere l'integrità delle transazioni, se l'architettura scelta deve avere transazioni strettamente gestite all'origine, cioè "solo lui che avvia la transazione, deve terminarlo". Questo, a parte i soliti fail-safe, ad es. se il codice non viene mai raggiunto a causa di un errore di sistema, ecc.
Nice articoli - grazie Dan. @ usr, i trigger devono essere a livello di DB, fanno parte dei vincoli estesi. In un sistema con più client (incluso SSIS), non è possibile applicare il controllo ovunque. Il mio esempio non ha fornito tutti i dettagli del controllo dei vincoli. Né Dan né l'articolo dicono di non lanciare errori in un trigger, dicono di non provare a sopprimere il rollback. – Gilbert