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?
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.
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
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
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.
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
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
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