Question

Je suis en train de comprendre que je dois utiliser ici. Supprimé, inséré ou mis à jour

essentiellement.

Je dois écrire des données à la table de l'histoire, lorsque la table principale est mis à jour, et que si les changements d'état de quelque chose soit en attente ou actif.

Voici ce que j'ai maintenant:

ALTER TRIGGER [dbo].[trg_SourceHistory]  ON [dbo].[tblSource]
FOR UPDATE AS  
    DECLARE @statusOldValue char(1) 
    DECLARE @statusNewValue char(1)

    SELECT @statusOldValue = statusCode FROM deleted 
    SELECT @statusNewValue= statusCode FROM updated

    IF (@statusOldValue <> @statusNewValue) AND 
       (@statusOldValue = 'P' or @statusOldValue = 'A')
    BEGIN TRY
       INSERT * INTO tblHistoryTable)  
           select * from [DELETED]

donc je veux que les nouvelles données pour rester dans le tableau principal, le tableau de l'histoire à être mis à jour avec ce qui est ... écrasé en ce moment il se contente de recopier les mêmes informations sur. donc après la mise à jour, mes deux tables ont les mêmes données.

Était-ce utile?

La solution

Vous devez utiliser à la fois les tables de inserted et deleted ensemble pour vérifier les dossiers que:
1. existait déjà (pour vérifier ce n'est pas un insert)
2. existe toujours (pour vérifier ce n'est pas une suppression)
3. Le champ d'état a changé

Vous devez également vous assurer que vous le faites dans une approche définie, selon la réponse de marc_s, les déclencheurs ne sont pas des processus d'enregistrement unique.

INSERT INTO
  tblHistoryTable
SELECT
  deleted.*
FROM
  inserted
INNER JOIN
  deleted
    ON inserted.PrimaryKey = deleted.PrimaryKey
WHERE
  inserted.StatusCode <> deleted.StatusCode
  AND (inserted.StatusCode = 'P' OR inserted.StatusCode = 'A')
  • = insérer les nouvelles valeurs
  • deleted = les anciennes valeurs

Autres conseils

Il n'y a que les tables pseudo Inserted et Deleted - il n'y a pas Updated.

Pour un UPDATE, Inserted contient les nouvelles valeurs (après la mise à jour), tandis que Deleted contient les anciennes valeurs avant la mise à jour.

Aussi sachez que les déclencheurs est tiré une fois par lot - pas une seule fois pour chaque ligne. Ainsi, les deux tables de pseudo contiennent potentiellement plusieurs lignes ! Ne présumez pas seulement une seule ligne et assigner à une variable - ce

SELECT @statusOldValue = statusCode FROM deleted 
SELECT @statusNewValue= statusCode FROM updated

échouera si vous avez plusieurs lignes! Vous devez écrire vos déclencheurs de telle façon qu'ils travaillent avec plusieurs lignes dans Inserted et Deleted!

Mise à jour: oui - il IS une bien meilleure façon d'écrire ceci:

ALTER TRIGGER [dbo].[trg_SourceHistory]  ON [dbo].[tblSource]
FOR UPDATE 
AS  
   INSERT INTO dbo.tblHistoryTable(Col1, Col2, Col3, ...., ColN)
      SELECT Col1, COl2, Col3, ..... ColN
        FROM Deleted d
        INNER JOIN Inserted i ON i.PrimaryKey = d.PrimaryKey
        WHERE i.statusCode <> d.statusCode
          AND d.statusCode IN ('A', 'P')

En gros:

  • spécifier explicitement les colonnes que vous souhaitez insérer - tant dans la déclaration de INSERT ainsi que la déclaration de SELECT récupérer les données à insérer - pour éviter les mauvaises surprises

  • créer une INNER JOIN entre les tables pseudo-Inserted et Deleted pour obtenir toutes les lignes qui ont été mis à jour

  • toutes les autres conditions préciser (différents codes d'état, etc.) dans la clause WHERE du SELECT

Cette solution fonctionne pour les lots de lignes étant mis à jour - il ne manquera pas sur une mise à jour à plusieurs rangs ....

Il n'y a pas de table de updated, vous cherchez inserted.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top