web-dev-qa-db-fra.com

Comment puis-je faire un déclencheur BEFORE UPDATED avec le serveur SQL?

J'utilise Sqlserver express et je ne peux pas faire before updated déclencheur. Il y a une autre façon de faire ça?

40
Bigballs

MSSQL ne prend pas en charge les déclencheurs BEFORE. Le plus proche que vous avez est INSTEAD OF se déclenche mais leur comportement est différent de celui des déclencheurs BEFORE dans MySQL.

Vous pouvez en savoir plus à leur sujet ici , et notez que INSTEAD OF triggers "Spécifie que le déclencheur est exécuté à la place de l'instruction SQL de déclenchement, remplaçant ainsi les actions des instructions de déclenchement." Ainsi, des actions sur la mise à jour peuvent ne pas avoir lieu si le déclencheur n'est pas correctement écrit/géré. Les actions en cascade sont également affectées.

Vous voudrez peut-être plutôt utiliser une approche différente de ce que vous essayez de réaliser.

36
achinda99

Il est vrai qu'il n'y a pas de "déclencheurs avant" dans MSSQL. Cependant, vous pouvez toujours suivre les modifications qui ont été apportées à la table, en utilisant les tables "insérées" et "supprimées" ensemble. Lorsqu'une mise à jour provoque le déclenchement du déclencheur, la table "insérée" stocke les nouvelles valeurs et la table "supprimée" stocke les anciennes valeurs. Une fois que vous disposez de ces informations, vous pouvez simuler relativement facilement le comportement "avant le déclenchement".

33
Stamen

Je ne peux pas être sûr que cela s'applique à SQL Server Express, mais vous pouvez toujours accéder aux données "avant" même si votre déclencheur se produit APRÈS la mise à jour. Vous devez lire les données de la table supprimée ou insérée qui est créée à la volée lorsque la table est modifiée. C'est essentiellement ce que dit @Stamen, mais j'avais encore besoin d'explorer davantage pour comprendre cette réponse (utile!).

La table supprimée stocke des copies des lignes affectées lors des instructions DELETE et UPDATE. Lors de l'exécution d'une instruction DELETE ou UPDATE, les lignes sont supprimées de la table de déclenchement et transférées vers la table supprimée ...

La table insérée stocke des copies des lignes affectées lors des instructions INSERT et UPDATE. Lors d'une transaction d'insertion ou de mise à jour, de nouvelles lignes sont ajoutées à la fois à la table insérée et à la table de déclenchement ...

https://msdn.Microsoft.com/en-us/library/ms191300.aspx

Vous pouvez donc créer votre déclencheur pour lire les données de l'une de ces tables, par exemple.

CREATE TRIGGER <TriggerName> ON <TableName>
AFTER UPDATE
AS
  BEGIN
    INSERT INTO <HistoryTable> ( <columns...>, DateChanged )
    SELECT <columns...>, getdate()
    FROM deleted;
  END;

Mon exemple est basé sur celui ici:

http://www.seemoredata.com/en/showthread.php?134-Example-of-BEFORE-UPDATE-trigger-in-Sql-Server-good-for-Type-2-dimension-table- mises à jour

sql-serverdéclencheurs

9
Charlie Joynt

T-SQL ne prend en charge que les déclencheurs AFTER et INSTEAD OF, il ne comporte pas de déclencheur BEFORE, comme dans certains autres SGBDR.

Je pense que vous voudrez utiliser un déclencheur AU LIEU DE.

8
Ian Nelson

Tous les déclencheurs "normaux" de SQL Server sont des déclencheurs "APRÈS ...". Il n'y a pas de déclencheurs "AVANT ...".

Pour faire quelque chose avant une mise à jour, consultez INSTEAD OF UPDATE Triggers .

3
Tomalak

Pour faire un BEFORE UPDATE dans SQL Server j'utilise une astuce. Je fais une fausse mise à jour de l'enregistrement (UPDATE Table SET Field = Field), de cette manière, j'obtiens l'image précédente de l'enregistrement.

2
Luciano

N'oubliez pas que lorsque vous utilisez un déclencheur à la place, il ne valide pas l'insertion, sauf si vous le lui demandez spécifiquement dans le déclencheur. Au lieu de signifie vraiment faire ceci au lieu de ce que vous faites normalement, donc aucune des actions d'insertion normales ne se produirait.

1
HLGEM

Exemple complet:

CREATE TRIGGER [dbo].[trig_020_Original_010_010_Gamechanger]
   ON  [dbo].[T_Original]
   AFTER UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @Old_Gamechanger int;
    DECLARE @New_Gamechanger int;

    -- Insert statements for trigger here
    SELECT @Old_Gamechanger = Gamechanger from DELETED;
    SELECT @New_Gamechanger = Gamechanger from INSERTED;

    IF @Old_Gamechanger != @New_Gamechanger

        BEGIN

            INSERT INTO [dbo].T_History(ChangeDate, Reason, Callcenter_ID, Old_Gamechanger, New_Gamechanger)
            SELECT GETDATE(), 'Time for a change', Callcenter_ID, @Old_Gamechanger, @New_Gamechanger
                FROM deleted
            ;

        END

END
0
Nick Oetjen