Domanda

Sto cercando di scrivere un trigger su una tabella per evitare l'inserimento di due nomi che non sono contrassegnati come IsDeleted. Ma la prima parte della selezione contiene quella inserita e quindi la condizione è sempre vera. Ho pensato che l'uso della parola chiave FOR causa l'esecuzione del trigger prima di INSERTION ma in questo caso la riga inserita è già nella tabella. Sbaglio o è così che funzionano tutti i trigger FOR?

ALTER TRIGGER TriggerName
ON MyTable
FOR INSERT, UPDATE
AS
BEGIN 
    If exist (select [Name] From MyTable WHERE IsDeleted = 0 AND [Name] in (SELECT [Name] FROM INSERTED)
    BEGIN
    RAISERROR ('ERROR Description', 16, 1);
    Rollback;
    END  
END
È stato utile?

Soluzione

FOR viene eseguito dopo la modifica dei dati, INSTEAD OF è ciò che penso tu stia cercando.

EDIT: come affermato da altri, INSTEAD OF viene eseguito invece dei dati che si stanno modificando, pertanto è necessario inserire i dati se sono validi, anziché interrompere l'inserimento se non è valido.

Leggi questa domanda per una spiegazione molto più dettagliata dei tipi di trigger.

SQL Server " AFTER INSERT " il trigger non vede la riga appena inserita

Altri suggerimenti

FOR è uguale a AFTER. se vuoi " simulare " PRIMA del trigger, utilizzare INSTEAD OF, avvertenza, non è esattamente quello che ci si aspetterebbe dal corretto trigger PRIMA, ovvero se non si fornisce l'azione INSTEAD necessaria, i dati inseriti / aggiornati potrebbero andare persi / ignorati.

MSSQL non ha PRIMA l'attivazione.

Per SQL Server, FOR esegue DOPO l'SQL che lo ha attivato.

Da: http://msdn.microsoft.com/en-us/library/ms189799. aspx

  

FOR | DOPO

     

DOPO specifica che il trigger DML   viene attivato solo quando tutte le operazioni   specificato nell'innesco di SQL   dichiarazione eseguita correttamente.   Tutte le azioni a cascata referenziali e   anche i controlli dei vincoli devono avere esito positivo   prima che questo grilletto si attivi.

     

DOPO è l'impostazione predefinita quando FOR è il   è stata specificata solo la parola chiave.

     

DOPO si innesca   non può essere definito nelle viste.

Ultimamente ho riscontrato un problema simile di recente e ho trovato un modo fantastico per gestirlo. Avevo una tabella che poteva avere più righe per un ID, ma solo UNA di esse poteva essere contrassegnata come primaria.

In SQL Server 2008, sarai in grado di creare un indice univoco parziale simile a questo:

create unique index IX on MyTable(name) where isDeleted = 0;

Tuttavia, puoi eseguirlo con un po 'più di lavoro in SQL Server 2005. Il trucco è creare una vista che mostri solo le righe che non sono state cancellate, e quindi creare un indice cluster univoco su di esso:

 create view MyTableNotDeleted_vw
 with schema_binding /* Must be schema bound to create an indexed view */
 as
 select name 
 from dbo.MyTable /* Have to use dbo. for schema bound views */
 where isDeleted = 0;

 GO

 create unique clustered index IX on MyTableNotDeleted_vw ( name );

Questo creerà effettivamente un vincolo unico che riguarda solo le righe che non sono ancora state eliminate e probabilmente funzionerà meglio di un trigger personalizzato!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top