Publié le 28/05/2008 par Another
Imaginons que vous ayez une table "Produits", et que pour des raisons diverses votre base de données étant dénormalisé, vous souhaitez mettre à jour la table "Produits_Histo" dés lors que vous modifier la colonne "intituleProduit". Je dis bien imaginons car de manière générale je ne vous encourage pas à développer ce genre de solution, beaucoup de gens vous dirons que ce n'est pas bien, moi le premier, mais faut parfois faire ce qu'on peut avec ce qu'on a, alors me soyons pas trop con-descendant , et regardons ensemble une solution implémentable dans le monde réel.
Oracle permet de créer des Triggers FOR EACH ROW, dans lesquels vous déclarer les références : NEW et :OLD afin de pouvoir accéder au valeur de la ligne avant la modification et après la modification.
Un trigger FOR EACH ROW s'exécute pour chacune des lignes modifiées, nous pourrions alors facilement mettre en place notre solution dans un trigger de ce type en utilisant le code suivant :
If :NEW. intituleProduit <> :OLD. intituleProduit Then
update Produits_Histo set intituleProduit = :NEW. intituleProduit
End If
SQL Server en revanche ne gère le Trigger FOR UPDATE que de manière ensembliste, on n'a pas la granularité ligne à ligne de Oracle.
Comme je vous le disais précédemment, un Trigger FOR UPDATE sous SQL Server est ensembliste, c'est à dire, que le trigger va s'exécuter qu'une fois lorsque tous les enregistrements auront étés mis à jour.
Dans un trigger, SQL Server permet d'accéder á deux pseudo-table nommé DELETED et INSERTED qui contienne respectivement les données avant UPDATE et les données après UPDATE.
Pour obtenir le même résultat que dans le chapite précédent, il faut créer un curseur reliant les deux tables, le parcourir avec FETCH et procéder a la mise à jour des enregistrements dans la boucle de lecture.
Pour exemple :
CREATE TRIGGER dbo.TRG_AU_PRODUITS ON dbo.Produits AFTER UPDATE AS BEGIN SET NOCOUNT ON; DECLARE @productId int, @newName varchar(50) DECLARE updateCursor CURSOR FOR SELECT Inserted.customerId, Inserted.productName AS afterName, Deleted .productName AS beforeName FROM Inserted, Deleted WHERE Inserted.productId = DEL.productId AND Inserted.productName <> Deleted.productName OPEN updateCursor FETCH NEXT FROM updateCursor INTO @productId, @newName IF @@FETCH_STATUS <> 0 RETURN WHILE @@FETCH_STATUS = 0 BEGIN UPDATE dbo.Products_Histo SET productName = @newName WHERE productId = productId FETCH NEXT FROM updateCursor INTO @productId, @newName END CLOSE updateCursor DEALLOCATE updateCursor END GO