2009-05-14 3 views
1

Ich habe einen SQL-Server "anstelle von Einfügen" Auslöser, der eine einzelne Spalte (PromoCode) füllt. Es funktioniert alles perfekt, aber ich weiß nicht, wie die Tatsache, das ich je hatte die Spalten in der tatsächlichen INSERT-Anweisung zu codieren:Vermeiden Sie Hardcoding beim Ändern von Werten in SQL Server-Trigger

CREATE TRIGGER PopulateOrderPromoCode ON Order 
INSTEAD OF INSERT 
AS BEGIN 
    --// Get the Promo Code 
    DECLARE @PromoCode int; 
    EXEC GetPromoCode @PromoCode OUTPUT;  

    --// Insert the order with the new Promo Code 
    INSERT INTO Order (Id, CustomerId, PromoCode) 
     SELECT Id, CustomerId, @PromoCode FROM inserted; 
END 

Ich ziehe es würde den Wert innerhalb inserted.PromoCode mit @PromoCode einfach zu ersetzen und dann konnte Verwenden Sie:

Kann dies getan werden?

+1

Sind Sie sicher, dass Sie immer nur eine Zeile nacheinander einfügen? Wenn jemand (z. B. ein DBA, der einen Tisch spät nachts repariert) jemals mehrere Zeilen in eine Anweisung einfügt, wird allen eingefügten Zeilen der gleiche @ PromoCode-Wert zugewiesen. –

+0

Massenkopie irgendjemand? – NotMe

Antwort

0

INSERTED ist eine schreibgeschützte temporäre Tabelle, auf die in jedem Trigger zugegriffen werden kann. Sie können es nicht ändern.

Und die Art, wie Sie einen INSERT ausführen, ist der beste Weg. Also, es ist nichts falsch daran. Es ist gut, die Spalten anzugeben, während ein INSERT (nach mir) ausgeführt wird.

+0

True, aber aktuell muss der Trigger aktualisiert werden, wenn Spalten zur Auftragstabelle hinzugefügt werden! Idealerweise wäre der Trigger transparent, da er nur auf die Order.PromoCode-Spalte wirkt und nicht an anderen Order-Spalten interessiert sein sollte. – user97280

-2

Dynamic SQL wäre Ihre einzige andere Option. Versuchen Sie folgendes:

CREATE TRIGGER PopulateOrderPromoCode 
ON Order 
INSTEAD OF INSERT 
AS 
BEGIN  
    --// Get the Promo Code  
    DECLARE @PromoCode int;   
    EXEC GetPromoCode @PromoCode OUTPUT;  

    DECLARE @InsertSQL nvarchar(2000), @SelectSQL nvarchar(2000) 
    SET @InsertSQL = 'INSERT INTO Order (' 
    SET @SelectSQL = 'SELECT ' 

    DECLARE @CurrentCol sysname 
    SET @CurrentCol = '' 



    WHILE EXISTS ( SELECT TOP 1 QUOTENAME(name) 
        FROM sys.syscolumns 
        WHERE object_name(id) = 'Order' 
        AND  name <> 'PromoCode' 
        AND  name > @CurrentCol) 
    BEGIN 
     SET @CurrentCol = (SELECT TOP 1 QUOTENAME(name) 
          FROM sys.syscolumns 
          WHERE object_name(id) = 'Order' 
          AND  name <> 'PromoCode' 
          AND  QUOTENAME(name) > @CurrentCol 
          ORDER BY name) 
     IF @CurrentCol IS NULL Break; 

     SET @InsertSQL = @InsertSQL + @CurrentCol + ', ' 
     SET @SelectSQL = @SelectSQL + @CurrentCol + ', ' 
    END 

    --Finish and concatenate the strings 
    SET @InsertSQL = @InsertSQL + 'PromoCode) ' 
    SET @SelectSQL = @SelectSQL + '''' + @PromoCode + '''' + ' FROM INSERTED' 

    DECLARE @MasterSQL nvarchar(2000) 
    SET @MasterSQL = @InsertSQL + @SelectSQL 

    EXEC (@MasterSQL) 
END 

BTW - „Ordnung“ ist eine schlechte Wahl für einen Tabellennamen - es ist auch ein reserviertes Wort in SQL. Versuchen Sie Orders oder OrderHeader.

2

Sie keinen STATT INSERT-Trigger verwendet

verwendet, einen normalen INSERT-Trigger (in dem Sie über den Einsatz Logik nehmen)

(die Ihnen Sachen neben der Einsatz erlaubt, zu tun)

Dies setzt voraus, dass Sie ohne einen Promo-Code einfügen können (erlaubt Nullen) oder die Promo-Code-Standards auf etwas.

CREATE TRIGGER PopulateOrderPromoCode ON Order 
FOR INSERT 
AS 
BEGIN 
    --// Get the Promo Code 
    DECLARE @PromoCode int;  
    EXEC GetPromoCode @PromoCode OUTPUT;   

    --// update the order with the new Promo Code 
    UPDATE Order SET PromoCode = @PromoCode 
     WHERE ID IN (SELECT ID FROM inserted) 
END 
Verwandte Themen