Trigger pour historisation de données
Bonjour
Afin de pouvoir gérer l'historique de ma base à chaque changement, j'ai pensé que des triggers pouvaient m'aider.
C'est mon premier contact avec ces bestioles là, et autant dire tout de suite que je suis pas une star en T-SQL ;)
Pour schématiser, voici le mécanisme que j'aimerais mettre en oeuvre :
2 tables, une parent et une enfant, qui ont chacune une colonne de données (c'est pour simplifier), et l'horodatage.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| CREATE TABLE dbo.Parent
(
idParent uniqueidentifier NOT NULL,
ValeurParent int NOT NULL,
DateDebut datetime NOT NULL,
DateFin datetime NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Parent ADD CONSTRAINT
DF_Parent_DateDebut DEFAULT getdate() FOR DateDebut
GO
ALTER TABLE dbo.Parent ADD CONSTRAINT
PK_Parent PRIMARY KEY CLUSTERED
(
idParent
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Parent SET (LOCK_ESCALATION = TABLE)
GO
CREATE TABLE dbo.Enfant
(
idEnfant uniqueidentifier NOT NULL,
idParent_FK uniqueidentifier NOT NULL,
ValeurEnfant int NOT NULL,
DateFin datetime NULL,
DateDebut datetime NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Enfant ADD CONSTRAINT
DF_Enfant_DateDebut DEFAULT getdate() FOR DateDebut
GO
ALTER TABLE dbo.Enfant ADD CONSTRAINT
PK_Enfant PRIMARY KEY CLUSTERED
(
idEnfant
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Enfant ADD CONSTRAINT
FK_Enfant_Parent FOREIGN KEY
(
idParent_FK
) REFERENCES dbo.Parent
(
idParent
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.Enfant ADD CONSTRAINT
FK_Enfant_PetitEnfant FOREIGN KEY
(
idEnfant
) REFERENCES dbo.PetitEnfant
(
idPetitEnfant
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO |
Lorsque ValeurParent change, voici ce que j'ai voulu implémenter dans mon trigger :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| DECLARE @NewID as uniqueidentifier
SET @NewID = NewID()
-- On remet les anciennes valeurs dans la ligne mise à jour
UPDATE Parent
SET DateFin = GETDATE(),
ValeurParent = Deleted.ValeurParent
FROM Parent, Deleted
WHERE Parent.idParent = Deleted.idParent
-- On crée la ligne avec les valeurs à jour
INSERT INTO Parent
(idParent, ValeurParent, DateDebut)
SELECT
@NewID,
Inserted.ValeurParent,
GETDATE()
FROM Inserted
-- Et on pousse la mise à jour vers les enfants
UPDATE Enfant
SET idParent_fk = @NewID
FROM Enfant, Deleted
WHERE Enfant.idParent_FK = Deleted.idParent
AND Enfant.DateEnd IS NULL |
Jusque là, tout va bien.
Mais du coup, comme le parent a changé, il faut changer les enfants aussi.
Et donc, un autre Trigger, sur la table enfant cette fois.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| DECLARE @NewID as uniqueidentifier
SET @NewID = NewID()
-- On remet les anciennes valeurs dans la ligne mise à jour
UPDATE Enfant
SET DateFin = GETDATE(),
ValeurEnfant = Deleted.ValeurEnfant,
idParent_FK = Deleted.idParent_FK
FROM Enfant, Deleted
WHERE Enfant.idEnfant = Deleted.idEnfant
-- On crée la ligne avec les valeurs à jour
INSERT INTO Enfant
(idEnfant, idParent_FK, ValeurEnfant, DateDebut)
SELECT
@NewID,
Inserted.idParent_FK,
Inserted.ValeurParent,
GETDATE()
FROM Inserted |
Et ca marche très bien... Tant qu'il y a qu'un enfant à modifier !
J'ai lu qu'il fallait traiter les triggers de manière ensembliste, et ne pas utiliser de variable locale dedans.
Le problème c'est le NewID() de l'enfant, je ne vois pas comment créer un nouveau GUID pour chaque ligne de la table Enfant qui va être recréée depuis le Trigger.
Merci pour votre aide