2009-04-29 6 views
2

Ich versuche, einen Trigger für eine Tabelle zu schreiben, um die Einfügung von zwei Namen zu vermeiden, die nicht als IsDeleted gekennzeichnet sind. Aber der erste Teil der Auswahl enthält den eingefügten, und so ist die Bedingung immer wahr. Ich denke, dass die Verwendung des FOR-Schlüsselwortes dazu führt, dass der Trigger vor der INSERTION ausgeführt wird, aber in diesem Fall befindet sich die eingefügte Zeile bereits in der Tabelle. Habe ich mich geirrt oder funktionieren alle FOR Trigger?Warum FOR Trigger wird nicht vor der Aktion ausgeführt?

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 

Antwort

2

FOR Läufe, nachdem die Daten geändert werden, INSTEAD OF ist, was ich denke, Sie sind danach.

BEARBEITEN: Wie von anderen angegeben, wird anstelle der Daten, die Sie ändern, INSTEAD OF ausgeführt, daher müssen Sie die Daten einfügen, wenn sie gültig ist, statt die Einfügung anzuhalten, wenn sie ungültig ist.

Lesen Sie diese Frage für eine viel detailliertere Erklärung der Arten von Triggern.

SQL Server "AFTER INSERT" trigger doesn't see the just-inserted row

+0

Stattdessen bedeutet, dass der Trigger ausgeführt wird anstelle des Befehls, den Sie ausführen –

1

FüR ist das gleiche wie nach. Wenn Sie BEFORE Trigger "simulieren" wollen, verwenden Sie INSTEAD OF, caveat, es ist nicht genau das, was Sie bei richtigem VORHER-Trigger erwarten würden, d.h. wenn Sie die notwendige INSTEAD Aktion nicht liefern, könnten Ihre eingefügten/aktualisierten Daten verloren/ignoriert werden.

MSSQL hat keinen BEFORE-Trigger.

0

Bei SQL Server läuft FOR nach der SQL, die es ausgelöst hat.

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

FÜR | NACH

NACH gibt an, dass der DML-Trigger nur ausgelöst, wenn alle Operationen in der Anweisung auslösenden SQL angegeben erfolgreich ausgeführt haben. Alle referenziellen Kaskadenaktionen und Constraint-Prüfungen müssen auch erfolgreich sein, bevor dieser Trigger ausgelöst wird .

NACH ist der Standardwert, wenn FOR das Schlüsselwort ist.

NACH Auslöser können nicht in Ansichten definiert werden.

0

Ich habe in letzter Zeit tatsächlich in ein ähnliches Problem gerannt, und fand einen coolen Weg, damit umzugehen. Ich hatte einen Tisch, der mehrere Reihen für eine ID haben konnte, aber nur EINER von ihnen konnte als primär markiert werden.

In SQL Server 2008, werden Sie in der Lage sein, einen Teil eindeutigen Index, so etwas zu machen:

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

aber Sie können es erreichen mit einem wenig mehr Arbeit in SQL Server 2005.Der Trick ist, eine Ansicht macht nur die Zeilen zeigt, die nicht gelöscht werden, und dann einen eindeutigen gruppierten Index für sie erstellen:

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); 

Dies wird effektiv eine eindeutige Einschränkung nur erstellen Reihen zu beeinflussen, die noch nicht gewesen sein gelöscht, und wird wahrscheinlich besser als ein benutzerdefinierter Trigger ausführen!

Verwandte Themen