it-swarm.com.de

SQL Server nach Update-Auslöser

Ich habe ein Problem mit diesem Auslöser. Ich möchte, dass die angeforderten Informationen Nur in der betreffenden Zeile (der gerade aktualisierten) und nicht in der gesamten Tabelle aktualisiert werden. 

CREATE TRIGGER [dbo].[after_update] 
    ON [dbo].[MYTABLE]
    AFTER UPDATE
    AS 
    BEGIN
          UPDATE MYTABLE 
          SET mytable.CHANGED_ON = GETDATE(),
          CHANGED_BY=USER_NAME(USER_ID())

Wie sage ich dem Auslöser, dass dies nur für die betreffende Zeile gilt?

15
user3927897

Hier ist mein Beispiel nach einem Test

CREATE TRIGGER [dbo].UpdateTasadoresName 
ON [dbo].Tasadores  
FOR  UPDATE
AS 
      UPDATE Tasadores 
      SET NombreCompleto = RTRIM( Tasadores.Nombre + ' ' + isnull(Tasadores.ApellidoPaterno,'') + ' ' + isnull(Tasadores.ApellidoMaterno,'')    )  
      FROM Tasadores 
    INNER JOIN INSERTED i ON Tasadores.id = i.id

Die eingefügte spezielle Tabelle enthält die Informationen aus dem aktualisierten Datensatz. 

15
Juan

Versuchen Sie dies (Update, nicht nach Update) 

CREATE TRIGGER [dbo].[xxx_update] ON [dbo].[MYTABLE]
    FOR UPDATE
    AS
    BEGIN

        UPDATE MYTABLE
        SET mytable.CHANGED_ON = GETDATE()
            ,CHANGED_BY = USER_NAME(USER_ID())
        FROM inserted
        WHERE MYTABLE.ID = inserted.ID

    END
5

Es ist sehr einfach, Erstellen Sie zuerst eine Kopie Ihrer Tabelle, für die Sie das Protokoll behalten möchten Zum Beispiel haben Sie die Tabelle dbo.SalesOrder mit den Spalten SalesOrderId, Vorname, Nachname, LastModified

Ihre Version-Archivtabelle sollte dbo.SalesOrderVersionArchieve mit den Spalten SalesOrderVersionArhieveId, SalesOrderId, Vorname, Nachname, LastModified sein

So richten Sie einen Auslöser für die SalesOrder-Tabelle ein

USE [YOURDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Karan Dhanu
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE TRIGGER dbo.[CreateVersionArchiveRow]
   ON  dbo.[SalesOrder]
  AFTER Update
AS 
BEGIN

    SET NOCOUNT ON;
INSERT INTO dbo.SalesOrderVersionArchive

   SELECT *
   FROM deleted;

END

Wenn Sie jetzt Änderungen in der saleOrder-Tabelle vornehmen, wird die Änderung in der VersionArchieve-Tabelle angezeigt

3
kdnerd

versuchen Sie diese Lösung.

   DECLARE @Id INT
   DECLARE @field VARCHAR(50)

   SELECT @Id= INSERTED.CustomerId       
   FROM INSERTED

   IF UPDATE(Name)
   BEGIN
          SET @field = 'Updated Name'
   END

   IF UPDATE(Country)
   BEGIN
          SET @field = 'Updated Country'
   END

   INSERT INTO CustomerLogs
   VALUES(@Id, @field)

Ich habe dies nicht mit einer älteren Version von SQL Server überprüft, dies funktioniert jedoch mit SQL Server 2012.

1
Hardik

Sie sollten in der Lage sein, auf die Tabelle INSERTED zuzugreifen und die ID oder den Primärschlüssel der Tabelle abzurufen. Etwas ähnlich zu diesem Beispiel ...

CREATE TRIGGER [dbo].[after_update] ON [dbo].[MYTABLE]
AFTER UPDATE AS 
BEGIN
    DECLARE @id AS INT
    SELECT @id = [IdColumnName]
    FROM INSERTED

    UPDATE MYTABLE 
    SET mytable.CHANGED_ON = GETDATE(),
    CHANGED_BY=USER_NAME(USER_ID())
    WHERE [IdColumnName] = @id

Hier ist ein Link in MSDN zu den Tabellen INSERTED und DELETED, wenn Trigger verwendet werden: http://msdn.Microsoft.com/en-au/library/ms191300.aspx

1
Kane

Zunächst einmal wird Ihr Trigger, wie Sie bereits sehen, jeden Datensatz in der Tabelle aktualisieren. Es wird keine Filterung durchgeführt, um nur die geänderten Zeilen auszuführen.

Zweitens gehen Sie davon aus, dass sich nur eine Zeile im Stapel ändert, was falsch ist, da sich mehrere Zeilen ändern könnten.

Um dies richtig zu tun, verwenden Sie die virtuell eingefügten und gelöschten Tabellen: http://msdn.Microsoft.com/en-us/library/ms191300.aspx

0
Sean Gallardy

Verwenden Sie dieses Skript, um eine temporäre Tabelle TESTTEST zu erstellen, und achten Sie auf die Rangfolge beim Aufruf der Trigger in dieser Reihenfolge:

Die gesamte Logik befindet sich im INSTEAD OF-Trigger. Ich habe zwei Beispiele, wie Sie einige Szenarien codieren könnten.

Viel Glück...

CREATE TABLE TESTTEST
(
    ID  INT,
    Modified0 DATETIME,
    Modified1 DATETIME
)
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_0] ON [dbo].TESTTEST
INSTEAD OF INSERT,UPDATE,DELETE
AS
BEGIN
    SELECT 'INSTEAD OF'
    SELECT 'TT0.0'
    SELECT * FROM TESTTEST

    SELECT *, 'I' Mode
    INTO #work
    FROM INSERTED

    UPDATE #work SET Mode='U' WHERE ID IN (SELECT ID FROM DELETED)
    INSERT INTO #work (ID, Modified0, Modified1, Mode)
    SELECT ID, Modified0, Modified1, 'D'
    FROM DELETED WHERE ID NOT IN (SELECT ID FROM INSERTED)

    --Check Security or any other logic to add and remove from #work before processing
    DELETE FROM #work WHERE ID=9 -- because you don't want anyone to edit this id?!?!
    DELETE FROM #work WHERE Mode='D' -- because you don't want anyone to delete any records

    SELECT 'EV'
    SELECT * FROM #work

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='I'))
    BEGIN
        SELECT 'I0.0'
        INSERT INTO dbo.TESTTEST (ID, Modified0, Modified1)
        SELECT ID, Modified0, Modified1
        FROM #work
        WHERE Mode='I'
        SELECT 'Cool stuff would happen here if you had FOR INSERT or AFTER INSERT triggers.'
        SELECT 'I0.1'
    END

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='D'))
    BEGIN
        SELECT 'D0.0'
        DELETE FROM TESTTEST WHERE ID IN (SELECT ID FROM #work WHERE Mode='D')
        SELECT 'Cool stuff would happen here if you had FOR DELETE or AFTER DELETE triggers.'
        SELECT 'D0.1'
    END

    IF(EXISTS(SELECT TOP 1 * FROM #work WHERE Mode='U'))
    BEGIN
        SELECT 'U0.0'
        UPDATE t SET t.Modified0=e.Modified0, t.Modified1=e.Modified1
        FROM dbo.TESTTEST t
        INNER JOIN #work e ON e.ID = t.ID
        WHERE e.Mode='U'
        SELECT 'U0.1'
    END
    DROP TABLE #work

    SELECT 'TT0.1'
    SELECT * FROM TESTTEST
END
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_1] ON [dbo].TESTTEST
FOR UPDATE
AS
BEGIN
    SELECT 'FOR UPDATE'

    SELECT 'TT1.0'
    SELECT * FROM TESTTEST

    SELECT 'I1'
    SELECT * FROM INSERTED

    SELECT 'D1'
    SELECT * FROM DELETED

    SELECT 'TT1.1'
    SELECT * FROM TESTTEST
END
GO
CREATE TRIGGER [dbo].[tr_TESTTEST_2] ON [dbo].TESTTEST
AFTER UPDATE
AS
BEGIN
    SELECT 'AFTER UPDATE'

    SELECT 'TT2.0'
    SELECT * FROM TESTTEST

    SELECT 'I2'
    SELECT * FROM INSERTED

    SELECT 'D2'
    SELECT * FROM DELETED

    SELECT 'TT2.1'
    SELECT * FROM TESTTEST
END
GO

SELECT 'Start'
INSERT INTO TESTTEST (ID, Modified0) VALUES (9, GETDATE())-- not going to insert
SELECT 'RESTART'
INSERT INTO TESTTEST (ID, Modified0) VALUES (10, GETDATE())--going to insert
SELECT 'RESTART'
UPDATE TESTTEST SET Modified1=GETDATE() WHERE ID=10-- gointo to update
SELECT 'RESTART'
DELETE FROM TESTTEST WHERE ID=10-- not going to DELETE
SELECT 'FINISHED'

SELECT * FROM TESTTEST
DROP TABLE TESTTEST
0
Tyler Feldkamp