web-dev-qa-db-fra.com

Comment un déclencheur T-SQL qui se déclenche uniquement sur des modifications réelles est-il effectué?

J'ai une table déclencheur sur UPDATE et INSERT qui ajoute une ligne à une autre table. Il n'a besoin d'ajouter une ligne que si l'une des quatre colonnes est modifiée. J'ai essayé d'utiliser IF UPDATE (col) pour tester les changements mais il a un angle mort. Il teste seulement qu'une certaine valeur est entrée. J'ai besoin d'approfondir, j'ai besoin de comparer les anciennes et les nouvelles valeurs pour voir qu'un vrai changement s'est produit. Il doit fonctionner avec INSERT et UPDATE.

Dans le cas d'une MISE À JOUR, c'est facile car les tables insérées et supprimées ont des valeurs que je peux comparer dans le déclencheur. Cependant, pour INSERT, seule la table d'insertion a des valeurs. Parce que j'ai besoin de tout cela dans le même déclencheur, comment gérer ce cas INSERT?

Voici le script du déclencheur que je souhaite modifier:

ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    -- Not all updates require a Push
    IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
    BEGIN
        INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
                [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
            )
        SELECT  [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
        FROM inserted 
    END
END
9
WillG

Vous pouvez gérer à la fois INSERT et UPDATE avec un opérateur set EXCEPT. Les EXISTS n'évalueront à VRAI que si c'est juste un INSERT, ou si c'est une MISE À JOUR avec des valeurs différentes pour l'une de ces colonnes.

IF EXISTS (
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM inserted
           EXCEPT
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM deleted
          )
BEGIN...
18
SQLRaptor

Dans le cas où une mise à jour peut affecter plusieurs lignes, vous devez vous protéger contre deux choses:

  1. Nous voulons considérer les mises à jour qui échangent des valeurs entre des lignes similaires. S'il y a deux John Smith qui ont besoin de mettre à jour leur JobCode (le premier John de 1 à 2; le second John de 2 à 1), nous devons faire attention à dire qu'ils ont tous les deux été mis à jour.
  2. Nous voulons uniquement enregistrer les lignes modifiées dans AT_Person_To_Push. Si 5 lignes sont mises à jour, mais seulement 2 sont mises à jour d'une manière qui nous tient à cœur, alors nous devons traiter uniquement les 2 lignes pertinentes.

Voici comment je le gérerais:

  1. Jointure gauche inserted à deleted, car inserted aura des lignes pour les insertions et les mises à jour tandis que deleted n'aura que des lignes pour les mises à jour.
  2. Utilisez EXISTS avec EXCEPT pour rechercher les lignes où les valeurs inserted diffèrent des valeurs deleted. Vous ne pouvez pas utiliser i.First_Name != d.First_Name OR i.Last_Name != d.Last_Name... car la table supprimée sera vide (et LEFT JOIN renverra des valeurs nulles) lorsque le déclencheur gère un INSERT.
  3. Insérez uniquement les lignes affectées dans AT_Person_To_Push.
ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
            [Facility],
            [VendorID],
            [Person_code],
            [First_Name],
            [Last_Name],
            [JobCode],
            [Alink],
            [Inactive]
        )
    SELECT  i.[Facility],
            i.[VendorID],
            i.[Person_code],
            i.[First_Name],
            i.[Last_Name],
            i.[JobCode],
            i.[Alink],
            i.[Inactive]
    FROM inserted i
         LEFT JOIN deleted d
           ON i.Person_code = d.Person_code
    -- Check for changes that require a Push
    WHERE EXISTS (SELECT i.[First_Name], i.[Last_Name], i.[JobCode], i.[Inactive]
                  EXCEPT
                  SELECT d.[First_Name], d.[Last_Name], d.[JobCode], d.[Inactive]);
END
2
Steven Hibble

Essaye ça,

Declare @Acton int=0

If exists (Select 1 from inserted)
set @Acton=1

If exists (Select 1 from deleted)
set @Acton=@Acton+2

if(@Action=1) -- Only insert

if(@Action=3) -- Only Update
begin
IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
Begin

End
end

if(@Action=2) -- Only Delete
1
KumarHarsh