web-dev-qa-db-fra.com

SQL Server après le déclenchement de la mise à jour

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?

15
user3927897

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. 

15
Juan

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
5
Homer J. Simpson

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

3
kdnerd

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.

1
Hardik

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

1
Kane

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

0
Sean Gallardy

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
0
Tyler Feldkamp