2010-01-29 3 views
6

ho qualche codice in un trigger di inserimento, dopo che potenzialmente possono fallire. Tale errore non è fondamentale e dovrebbe non eseguire il rollback della transazione. Come posso intercettare l'errore all'interno del trigger e far eseguire normalmente il resto della transazione?TSQL make grilletto fallire in silenzio

L'esempio seguente mostra cosa intendo. Il trigger crea intenzionalmente una condizione di errore con il risultato che l'inserimento originale ("1") non si inserisce mai nella tabella. Try/Catch non sembra fare il trucco. Una simile, older stack overflow question non ha dato una risposta fatta eccezione per "evitare che l'errore si verificano in primo luogo" - che non è sempre possibile/facile.

Altre idee?

create table test 
(
    a int not null 
); 
go 

create trigger testTrigger on test 
after insert as 
begin 
    insert into test select null; 
end; 
go 

insert into test values (1); 
+1

Perché provato/Catch non funziona? – cjk

+0

@ck: poiché le violazioni dei vincoli all'interno dei trigger provocano le transazioni. – Quassnoi

risposta

2

Un trigger non può fallire e mantenere il roll forward della transazione. Hai alcune opzioni per assicurarti che il trigger non fallisca.

1 - È possibile assicurarsi che il dopo non manca duplicando la logica per la verifica dei vincoli e non tentare un'operazione che violerebbe i vincoli:

cioè

INSERT INTO test WHERE val IS NOT NULL 

2 - È possibile posticipare l'azione potenzialmente omettendo utilizzando un modello di progettazione coda in cui le azioni che possono o non possono fallire vengono accodati da enqueueing a una tabella in cui l'operazione enqueueing non può assolutamente sicuro.

cioè

INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val) 
+0

Ho paura che questo sarebbe stato l'unico modo. È difficile però. Si prega di vedere il mio commento alla risposta di Quassnoi qui sotto. – BuschnicK

+0

@BuschnicK Creare i trigger è una delle cose più invasive che puoi fare in un sistema. Fa parte dello schema del database per l'applicazione del comportamento del database e lo stai facendo nel database di qualcun altro. Hanno il loro posto, ma non penso che questo uso sia appropriato SE non puoi assicurarti che si comportino bene.Francamente, se si utilizza un trigger come unico meccanismo per spedire le modifiche, se il trigger dovesse fallire in modo silenzioso, le modifiche non verrebbero spedite, tuttavia la transazione potrebbe essere completata e si perderebbe il "messaggio" di dati di modifica, come si farebbe risincronizzare i dati in modo affidabile in ogni caso? –

+0

@BuschnicK Sarebbe meglio esaminare una specie di modifica dei dati acquisiti o altra tecnica ETL per confrontare i cambiamenti dall'ultima istantanea. –

1

A causa del modo in cui i trigger sono implementati in SQL Server, tutte le violazioni dei vincoli entro i trigger destino delle transazioni.

questa è la stessa come fare:

DROP TABLE test 

CREATE TABLE test 
(
     a INT NOT NULL 
) 

GO 

SET XACT_ABORT ON 
GO 

BEGIN TRANSACTION 

BEGIN TRY 
     INSERT 
     INTO test 
     SELECT NULL 
END TRY 
BEGIN CATCH 
     INSERT 
     INTO test 
     SELECT 1 
END CATCH 

che si traduce in una transazione condannato, salvo che non v'è alcun modo per disattivare XACT_ABORT in un trigger.

SQL Server manca anche le operazioni autonome.

Questo è un altro motivo per cui è necessario inserire tutta la logica nelle stored procedure anziché in trigger.

+0

in realtà non si hanno transazioni compromesse se non si usa try..catch. –

+0

@Alex: certo, l'operazione è annullata atomicamente. Questo era solo per dimostrare cosa sta succedendo. – Quassnoi

+0

Come aiutano le stored procedure? Ho pensato che il trigger avrebbe chiamato la procedura memorizzata ... Per dare un po 'di informazioni di base su ciò che sto cercando di ottenere qui: Abbiamo un sistema ERP fornito dal fornitore e vogliamo ottenere dati aggiornati da sono tavoli Alleghiamo trigger alle loro tabelle, massaggiamo i dati e li copiamo nel nostro database. Vogliamo garantire che i nostri trigger non falliranno mai perché ciò potrebbe causare problemi nel sistema ERP originale. – BuschnicK

0
  1. È possibile disattivare XACT_ABORT off all'interno del grilletto (uso cautela)
  2. Si può avere il grilletto chiamare una stored procedure. (Sto ora lottando con il problema opposto: voglio la transazione interrotta, ma poiché la logica è in un SP chiamato dal trigger, e non il trigger stesso, questo non sta accadendo.)