J'ai un problème avec ce déclencheur. Je voudrais qu'il mette à jour les informations demandées Uniquement à la ligne en question (celle que je viens de mettre à jour) et non à la totalité du tableau.
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())
Comment puis-je dire au déclencheur que cela s'applique uniquement à la ligne en question?
Voici mon exemple après un 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
La table spéciale insérée aura les informations de l'enregistrement mis à jour.
Essayez ceci (mise à jour, pas après mise à jour)
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
C’est très simple, Créez d’abord une copie de votre table que vous souhaitez conserver dans le journal Par exemple, vous avez la Table dbo.SalesOrder avec les colonnes SalesOrderId, FirstName, LastName, LastModified.
Votre version de la table archieve doit être dbo.SalesOrderVersionArchieve avec des colonnes SalesOrderVersionArhieveId, SalesOrderId, FirstName, LastName, LastModified
Voici comment vous allez configurer un déclencheur sur la table SalesOrder
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
Maintenant, si vous apportez des modifications dans la table saleOrder, cela vous indiquera la modification dans la table VersionArchieve
essayez cette solution.
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)
Je n'ai pas vérifié cela avec l'ancienne version de SQL Server, mais cela fonctionnera avec SQL Server 2012.
Vous devriez pouvoir accéder à la table INSERTED
et récupérer l'ID ou la clé primaire de la table. Quelque chose de semblable à cet exemple ...
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
Voici un lien sur MSDN sur les tables INSERTED
et DELETED
disponibles lorsque vous utilisez des déclencheurs: http://msdn.Microsoft.com/en-au/library/ms191300.aspx
Tout d’abord, votre déclencheur, comme vous le voyez déjà, va mettre à jour tous les enregistrements de la table. Aucun filtrage n'est effectué pour accomplir les lignes modifiées.
Deuxièmement, vous supposez qu'une seule ligne du lot est incorrecte, ce qui est incorrect, car plusieurs lignes peuvent changer.
Pour le faire correctement, utilisez les tables virtuelles insérées et supprimées: http://msdn.Microsoft.com/en-us/library/ms191300.aspx
Essayez ce script pour créer une table temporaire TESTTEST et observez l'ordre de priorité car les déclencheurs sont appelés dans cet ordre: 1) INSTEAD OF, 2) FOR, 3) APRES
Toute la logique est placée dans le déclencheur INSTEAD OF et j'ai 2 exemples de la façon dont vous pourriez coder certains scénarios ...
Bonne chance...
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