2017-04-10 5 views
0

Ich habe mehrere Trigger verwendet, um backward date scheduling in Sqlserver mit Trigger zu implementieren.Hat Sql Server Trigger die Reihenfolge der Ausführung?

Aber hier ist etwas verdrahtet. hier ist, was ich

bemerkt
  • AFTER INSERT die folgenden drei Felder SHIP BY,A-MOUNT BY,A-POWDER BY aktualisiert
  • Wenn ich etwas auf denselben Datensatz ändern und speichern A-FAB
  • aktualisiert
  • Und zum zweiten Mal, wenn ich etwas auf denselben Datensatz ändern und speichern A-C\S, A-PRINT BY
  • aktualisiert

I 3 Mal aktualisieren, müssen alle Felder aktualisiert bekommen

Unten ist die Logik der Rückwärtsplanung. Alle Felder sind miteinander verknüpft

SCHIFF DURCH = CUSTOMER VERSPRACH DATE-1

A-MOUNT BY = SCHIFF VON -1

A-PULVER BY = A-MOUNT BY - 1 oder A-PULVER indem auch gleich Schiff durch Datum -2

A-FAB BY = A-POWDER BY - 1 oder A-FAB von ebenfalls gleich Schiff durch Datum -3

AC/S BY = A-FAB BY OR AC/S BY auch gleich Versanddatum -4

A-CUT BY = AC/S mit -1 oder A-Schnitt ebenfalls gleich Schiff durch Datum -5

/****** Object: Trigger [dbo].[CALC-PROMISED-DATE-AND-SHIPBY] Script Date: 4/6/2017 2:46:01 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[CALC-PROMISED-DATE-AND-SHIPBY] 
    ON [dbo].[WORKORDERS] 
    AFTER INSERT, UPDATE 
    AS 
    BEGIN 
    set nocount on 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
    [SHIP BY] = 
       CASE datepart(WEEKDAY, t1.[CALC PROMISED DATE]) 
        WHEN 1 then DateAdd(day, -2, t1.[CALC PROMISED DATE]) 
        WHEN 7 then DateAdd(day, -1, t1.[CALC PROMISED DATE]) 
       ELSE 
        CASE 
         WHEN t1.[RE-COMMIT DATE] =Null THEN ISNULL(T1.[PROMISED DATE],Null) 
         WHEN t1.[RE-COMMIT DATE] is null THEN ISNULL(T1.[PROMISED DATE],Null) 
        ELSE ISNULL(T1.[RE-COMMIT DATE],Null) 
        END 
      END  

      FROM WORKORDERS T1 
       INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
       END 

A-MOUNT BY

/****** Object: Trigger [dbo].[MOUNTBY] Script Date: 4/6/2017 2:46:54 PM ******/ 
    SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    ALTER TRIGGER [dbo].[MOUNTBY] 
     ON [dbo].[WORKORDERS] 
     AFTER INSERT,UPDATE 
     AS 
     BEGIN 
     IF TRIGGER_NESTLEVEL() > 1 
     RETURN 
     set datefirst 7; 
    UPDATE T1 
     [A-MOUNT BY] = 
     case  datepart(WEEKDAY, DateAdd(day,-1,t1.[SHIP BY])) 
      when 7 then DateAdd(day, -2, t1.[SHIP BY]) 
      when 1 then DateAdd(day, -3, t1.[SHIP BY]) 
      else DateAdd(day, -1, t1.[SHIP BY])--t1.[A-C/S BY]-1 
     END 
FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

A-BY POWDER

/****** Object: Trigger [dbo].[POWDERBY] Script Date: 4/6/2017 2:49:53 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[POWDERBY] 
    ON [dbo].[WORKORDERS] 
    AFTER INSERT,UPDATE 
    AS 
    BEGIN 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
--SET 
SET [A-POWDER BY] = 
case datepart(WEEKDAY, t1.[A-MOUNT BY]-1) 
     when 7 then DateAdd(day, -2, t1.[A-MOUNT BY]) 
    when 1 then DateAdd(day, -3, t1.[A-MOUNT BY]) 
    else t1.[A-MOUNT BY]-1 
END 

FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

A-FAB BY

/****** Object: Trigger [dbo].[FABBY] Script Date: 4/6/2017 2:50:23 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[FABBY] 
    ON [dbo].[WORKORDERS] 
    AFTER insert, UPDATE 
    AS 
    BEGIN 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
SET [A-FAB BY] = case datepart(WEEKDAY, t1.[A-POWDER BY]-1) 
     when 7 then DateAdd(day, -2, t1.[A-POWDER BY]) 
    when 1 then DateAdd(day, -3, t1.[A-POWDER BY]) 
    else t1.[A-POWDER BY]-1 
END 
FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

a-PRINT

VON
/****** Object: Trigger [dbo].[PRINTBY] Script Date: 4/6/2017 2:50:50 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[PRINTBY] 
    ON [dbo].[WORKORDERS] 
    AFTER INSERT, UPDATE 
    AS 
    BEGIN 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
SET [A-PRINT BY] = case datepart(WEEKDAY, t1.[A-FAB BY]) 
     when 7 then DateAdd(day, -2, t1.[A-FAB BY]) 
    when 1 then DateAdd(day, -3, t1.[A-FAB BY]) 
    else t1.[A-FAB BY]-1 
END 
FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

A-C/S BY

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[C/SBY] 
    ON [dbo].[WORKORDERS] 
    AFTER INSERT,UPDATE 
    AS 
    BEGIN 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
--SET 
SET [A-C/S BY] = case datepart(WEEKDAY, t1.[A-PRINT BY]-1) 
     when 7 then DateAdd(day, -2, t1.[A-PRINT BY]) 
    when 1 then DateAdd(day, -3, t1.[A-PRINT BY]) 
    else t1.[A-PRINT BY]-1 
END 
FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

A-CUT

VON
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[CUTBY] 
    ON [dbo].[WORKORDERS] 
    AFTER INSERT, UPDATE 
    AS 
    BEGIN 
    IF TRIGGER_NESTLEVEL() > 1 
    RETURN 
    set datefirst 7; 
UPDATE T1 
--SET 
SET [A-CUT BY] = 
case  datepart(WEEKDAY, DateAdd(day,-1,t1.[A-C/S BY])) 
    when 7 then DateAdd(day, -2, t1.[A-C/S BY]) 
    when 1 then DateAdd(day, -3, t1.[A-C/S BY]) 
    else t1.[A-C/S BY]-1--t1.[A-C/S BY]-1 
END 
FROM WORKORDERS T1 
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #] 
    END 

Ich frage mich, ob seine weil die Ordnung wenn überhaupt da? Wenn i auf einen alle oben genannten Trigger fusionieren nur die SHIP BY Feld aktualisiert der Rest leer auf null gesetzt

+0

Sie haben keine garantierte Reihenfolge der Ausführung, wenn Sie mehrere Trigger desselben Typs (INSERT, UPDATE, DELETE) in derselben Tabelle haben. Es ist möglich, einen von ihnen als den ersten immer zu spezifizieren, oder einen von ihnen, um immer der letzte zu sein, aber Sie können nicht eine volle Reihenfolge für mehr als diktieren. Ihre Auslöser sollten daher NIEMALS von der Reihenfolge abhängen, in der sie ausgeführt werden. Und ehrlich gesagt, sollte nicht mit den gleichen Daten arbeiten. – pmbAustin

+0

Wir haben das neulich besprochen, als ich gezeigt habe, wie Sie all diese Trigger in einer einzigen Update-Anweisung kombinieren können. http://StackOverflow.com/Questions/43265377/disadvantage-of-having-multiple-triggers-on-the-same-table –

+0

@SeanLange Wenn ich alle Trigger zu einem zusammenführen, wie Sie vorgeschlagen, nur das SHIP BY-Feld alle aktualisiert rest set to blank oder NULL – Joe

Antwort

0

Oh Mann - eine Menge von Triggern auf einer einzigen Tabelle, wie die ... schlecht juju hat, denke ich, ist die Ausführungsreihenfolge steuern Sie nicht ein Ansatz wollen nehmen. Wo einfach mehrere Auslöser sein müssen, sollten sie Arbeit machen, die nicht von anderen Auslösern abhängt, um ihre Arbeit zuerst zu erledigen. Sie sollten vollständiger isoliert sein.

Bevor wir dort ankommen, haben Sie Ausdrücke, die keinen Sinn in Ihrem ersten Trigger machen ... Dinge wie

WHEN t1.[RE-COMMIT DATE] =Null 

..., die Sie sollten nie/Verwendung finden, wenn ANSI_NULLS eingeschaltet ist (und das sollte immer eingeschaltet sein). Auch

... Dinge wie:

IsNull(t1.[Promised Date], Null) 

... entweder keinen Sinn machen. Dies sagt, gib den ersten Wert zurück ... aber wenn das Null ist, dann gib den zweiten Wert zurück. Wenn Sie dieses Zeug aus Ihrem Auslöser bekommen, wird es leichter zu verstehen sein.

Also ... wie bekommt man alles in einem einzigen Trigger? Ich würde damit beginnen, einen einzigen Auslöser zu setzen ... der empfindlich auf Änderungen der versprochenen Termine reagiert. Auf dieser Grundlage kann alles als geplant betrachtet werden. Das heißt, machen Sie Ihren Auslöser so offensichtlich wie es sein kann ... und delegieren Sie die geräuschvollen Teile an Funktionen, Verfahren und Ansichten nach Bedarf.

Also, ich würde all jene bösen Dinge fallen und beginnen Sie mit etwas einfach, wie ...

create trigger [SetWorkflowDates] on dbo.WORKORDERS for insert, update as 
begin 

    set nocount on, datefirst 7 

    update dbo.WORKORDERS 
    set 
     [Ship By]  = dbo.CalcDate('ship', [Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [Mount By] = dbo.CalcDate('mount', [Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [A-Powder By] = dbo.CalcDate('powder',[Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [A-Fab By] = dbo.CalcDate('fab', [Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [A-Print By] = dbo.CalcDate('print', [Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [A-C/S By] = dbo.CalcDate('cs', [Calc Promised Date],[Promised Date],[Re-Commit Date]), 
     [A-Cut By] = dbo.CalcDate('cut', [Calc Promised Date],[Promised Date],[Re-Commit Date]) 
    from 
    dbo.WORKORDERS wo 
    inner join 
    inserted i 
    on 
     wo.[Work Order #] = i.[Work Order #] 
    left outer join 
    deleted d 
    on 
     i.[Work Order #] = d.[Work Order #] 
    where 
    isnull(i.[Calc Promised Date],getdate()) != 
    isnull(d.[Calc Promised Date],getdate()) 
     or 
    isnull(i.[Promised Date],getdate()) != 
    isnull(d.[Promised Date],getdate()) 
     or 
    isnull(i.[Re-Commit Date],getdate()) != 
    isnull(d.[Re-Commit Date],getdate()) 
end 

Hinweis, dass dies die Bedingungen der Arbeit für Einfügung oder Aktualisierung vornehmen.

Schön und klein und klar und viel einfacher zu debuggen als eine ganze Reihe von Triggern.

Also ... der Trigger wird nicht kompiliert, bis Sie die CalcDate Funktion in dort definieren ... eine Funktion, die regulative Daten verwendet ... und berechnet ein anderes Datum, basierend auf der Bühne. Du bist gut bedient, um das aus dem Auslöser selbst zu bekommen ... nur damit du den Auslöser lesen und verstehen kannst, ohne deine Haare auszuziehen.

Vielleicht CalcDate könnte sein, so etwas wie:

create function dbo.CalcDate 
( 
    @stage varchar(8), @calc date, @prom date, @recommit date 
) 
returns date as 
begin 

    declare @result date = 
    case datepart(weekday, @calc) 
     when 7 then 
     dateadd(day, -1, @calc) 
     when 1 then 
     dateadd(day, -2, @calc) 
     else 
     coalesce(@recommit, @prom) 
    end 

    if (@stage = 'ship') return (@result); 

    set @result = dbo.PreviousWorkDay(@result);  
    if (@stage = 'mount') return (@result); 

    set @result = dbo.PreviousWorkDay(@result);  
    if (@stage = 'powder') return (@result); 

    set @result = dbo.PreviousWorkDay(@result); 
    if (@stage = 'fab') return (@result);  

    set @result = dbo.PreviousWorkDay(@result); 
    if (@stage = 'print') return (@result); 

    set @result = dbo.PreviousWorkDay(@result); 
    if (@stage = 'cs') return (@result); 

    set @result = dbo.PreviousWorkDay(@result); 
    if (@stage = 'cut') return (@result); 

    raiserror('Unrecognized stage', 16, 1); 

end 

... So, jetzt kann ich sehen, dass die CalcDate einen Arbeitsschritt auf der Bühne Basis berechnet ... und es ist einfach, wenn die Workflow-Regeln ändern zu aktualisieren .

... und dann schließlich die PreviousWorkDay Funktion subtrahiert einen Tag ... sieht, wenn es ein Arbeitstag ist, und wenn nicht, subtrahiert anderen, bis es ein Arbeitstag ist:

create function dbo.PreviousWorkDay(@date date) returns date as 
begin 
    set @date = dateadd(day, -1, @date) 
    return 
    (
    select case datepart(weekday, @date) 
     when 7 then dateadd(day, -1, @date) 
     when 1 then dateadd(day, -2, @date) 
     else @date 
    end 
) 
end 

der Code All dann machen sie Sinn - Funktionsnamen sagen, was sie tun ... sie versuchen nicht, zu viel (oder nicht genug) zu tun. Fixieren und Aktualisieren ist viel einfacher. Planen und vereinfachen Sie bei jeder Gelegenheit.

Hinweis: Sie sollten die vorherige Frage löschen. Es stört nur SO Leute, wenn Sie Fragen zweimal stellen, weil Sie die Antworten beim ersten Mal nicht mögen. Sie werden nicht immer freundlich behandelt, wenn Sie das tun.

+0

Vielen Dank @clay ich bekomme 'Msg 156, Level 15, Status 1, Prozedur SetWorkflowDates, Zeile 22 Falsche Syntax in der Nähe des Schlüsselwortes 'links'. Fehler in dieser Zeile' wo. [Arbeitsauftrag #] = i Order #], linker äußerer Join' – Joe

+0

mein böser ... es gibt ein Komma - ich werde es beheben - aber Sie müssen die Funktionen zuerst definieren ... so ziemlich in der umgekehrten Reihenfolge, die ich beschrieben habe. Dort - ich habe diesen Teil davon repariert. Keine Garantien, obwohl ... – Clay

+0

Ja, dass was ich tue, Danke – Joe

0

Quote from the manual

Die erste und letzte AFTER triggert auf einer Tabelle ausgeführt werden kann durch die Verwendung festgelegt werden sp_settriggerorder.Nur ein erster und ein letzter AFTER-Trigger für jede INSERT-, UPDATE- und DELETE-Operation kann für eine Tabelle angegeben werden. Wenn weitere AFTER-Trigger in derselben Tabelle vorhanden sind, werden sie nach dem Zufallsprinzip ausgeführt.

(Hervorhebung von mir)