2017-01-31 2 views
2

I Auslöser für meine Datenbank erstellt haben, die einige Insertion behandelt, aber wenn ich mehrere Werte in 1 SQL-Abfrage hinzufügen, funktioniert es nicht:SQL Server-Trigger mit Schleife für mehrreihige Einfügen

ALTER TRIGGER [dbo].[ConferenceDayTrigger] 
ON [dbo].[Conferences] 
AFTER INSERT 
AS 
BEGIN 
    DECLARE @ID INT 
    DECLARE @dayC INT 
    DECLARE @counter INT 

    SET @counter = 1 
    SET @ID = (SELECT IDConference FROM Inserted) 
    SET @dayC = (SELECT DATEDIFF(DAY, start,finish) FROM Inserted) 

    WHILE @counter <= @dayC + 1 
    BEGIN 
     EXEC AddConferenceDay @Id, @counter 
     SET @counter = @counter +1 
    END 
END 

Für einzelne Einfügung es funktioniert ok. Aber was sollte ich ändern/hinzufügen, damit es für jede Zeile der eingefügten Werte ausgeführt wird?

+2

Loops in SQL sind fast immer eine schreckliche Idee. Schleifen innerhalb von Triggern sind wie eine schlechte Idee im Quadrat. Jetzt kommst du vielleicht nicht herum und du musst es so machen, aber ich hoffe es nicht! PS Sie müssen die Zeilen in der "eingefügten" Tabelle durchlaufen, wahrscheinlich mit einem Cursor (eine andere schlechte Idee!) – DavidG

Antwort

0

Wenn Sie mehr als einen Datensatz einfügen, müssen Sie cursor/while die Prozedur AddConferenceDay für jeden Datensatz aufrufen.

Aber ich werde vorschlagen, dass Sie Ihre Prozedur ändern, um den Tabellentyp als Eingabeparameter zu akzeptieren. So dass mehr als eine ID und dayC als Eingabe für AddConferenceDay Verfahren. Es ist effizienter als Ihr aktueller Ansatz.

so etwas wie dieses

create type udt_Conferences as table (ID int,dayC int) 

Alter die Prozedur udt_Conferences als Eingangsparameter

Alter procedure AddConferenceDay (@input udt_Conferences readonly) 
as 
begin 
/* use @input table type instead of @Id and @counter variables */ 
end 

verwenden, um den Vorgang rufen Sie den Trigger mit erstellt UDT aktualisieren

ALTER TRIGGER [dbo].[ConferenceDayTrigger] 
ON [dbo].[Conferences] 
AFTER INSERT 
AS 
BEGIN 
Declare @input udt_Conferences 

insert into @input (ID,dayC) 
select IDConference,DATEDIFF(DAY, start,finish) from Inserted 
END 
1

Wenn Sie sich nicht Ändern Sie die gespeicherte Prozedur, dann könnte dies einer der (sehr wenigen) Fälle sein, wenn ein Cursor co mes zur Rettung. Doppelschleifen in der Tat:

ALTER TRIGGER [dbo].[ConferenceDayTrigger] 
ON [dbo].[Conferences] 
AFTER INSERT 
AS 
BEGIN 
    DECLARE @ID INT; 
    DECLARE @dayC INT; 
    DECLARE @counter INT 
    SET @counter = 1; 

    DECLARE yucky_Cursor CURSOR FOR 
     SELECT IDConference, DATEDIFF(DAY, start,finish) FROM Inserted; 
    OPEN my_Cursor; 

    FETCH NEXT FROM yucky_Cursor INTO @ID, @dayC; 
    WHILE @@FETCH_STATUS = 0 

     while @counter <= @dayC + 1 
     begin 
      EXEC AddConferenceDay @Id, @counter; 
      SET @counter = @counter + 1; 
     end; 
     FETCH NEXT FROM yucky_Cursor INTO @ID, @dayC; 
    END; 

    CLOSE yucky_Cursor; 
    DEALLOCATE yucky_Cursor; 
END; 

Ich vermute, es ist ein Weg, Refactoring und die Beseitigung der Cursor zu erhalten und verwenden Set-basierte Operationen.

+0

danke prefectly funktioniert –

0

fügen Sie diese Zeilen zu Ihrem Trigger

AFTER INSERT AS BEGIN

AFTER INSERT 
AS 
BEGIN 

    Declare @Count int; 
    Set @[email protected]@ROWCOUNT; 
    IF @Count=0 
    Return; 

    SET NOCOUNT ON; 

-- Insert statements for trigger here