L'utilisation de triggers à mauvais escient ou dans de mauvaises conditions peut altérer sérieusement les performances du serveur SQL et donc de Mercator.
De manière générale, il faut faire très attention à la mise en place d’un trigger dans un dossier.
Voici donc quelques règles à respecter lors de l’élaboration de triggers "customs" :
- Il ne faut jamais modifier un trigger standard, celui-ci est susceptible d’être réinstallé par Mercator lors d’une mise à jour.
- Un trigger peut concerner plusieurs enregistrements. Il faut donc toujours travailler avec les tables inserted/deleted, jamais avec des variables scalaires.
Exemple : update stock
set stock.s_cle3 = inserted.s_condit_a
from stock inner join inserted on inserted.s_id = stock.s_id
- En standard, il peut y avoir un trigger pour chaque opération (insert, update, delete). S'il s'avère nécessaire d'ajouter d'autres triggers, il faut regrouper ceux-ci pour n’avoir qu’un seul (au maximum) par opération.
L'idéal est de, si possible, regrouper les différentes opérations en un seul trigger; notamment les triggers "on insert" et "on update". Pour savoir si vous êtes en modification, il faut tester qu'il y ait un enregistrement dans la table deleted.
Exemple : if update(s_cle2) and exists(select * from deleted)
begin
IF @@TRANCOUNT > 0 ROLLBACK TRAN
RAISERROR ( 'Stock.s_cle2 ne peut être modifié!',16,1 )
return
end
- Il faut, au maximum, utiliser les syntaxes "if update(nomduchamp)" pour n'exécuter ce code que si le champ est réellement modifié (même en cas d’insert).
Ce principe n'est pas utilisable pour le delete.
Exemple : if update(s_cle2)
Ceci permet également d'éviter la récursivité des triggers. Cela peut se produire quand les champs (table STOCK, par exemple) mis à jour par un trigger, déclenchent eux-mêmes un autre trigger sur cette même table (qui pourrait mettre à jour un des champs gérés par le premier trigger). Une boucle infinie est alors générée.
- Vu l’importance d’un trigger par rapport aux performances, il ne faut pas chercher à faire un "beau" trigger bien lisible, mais il faut, au maximum, optimiser celui-ci pour avoir le moins d’impact possible sur les performances.
Exemple : if update(s_taux_tva)
begin
update stock
set stock.s_comptev = case when inserted.s_compte_manuel = 1 then stock.s_comptev when inserted.s_articlenormal = 0 then '700000' else '700210' end,
stock.s_comptea = case when inserted.s_compte_manuel = 1 then stock.s_comptev when inserted.s_articlenormal = 0 then '604000' else '604210' end
from stock inner join inserted on inserted.s_id = stock.s_id
end
if update(s_type_etiq)
begin
update stock
set stock.s_etiq = case when stock.s_type_etiq = 'CARTON' then '3' when stock.s_type_etiq = 'COLLANTE' then '2' else '1' end
from stock inner join inserted on inserted.s_id = stock.s_id
end
if update(s_condit_a)
begin
update stock
set stock.s_cle3 = inserted.s_condit_a
from stock inner join inserted on inserted.s_id = stock.s_id
end
devient : if update(s_taux_tva) or update(s_type_etiq) or update(s_condit_a)
begin
update stock
set stock.s_comptev = case when inserted.s_compte_manuel = 1 then stock.s_comptev when inserted.s_articlenormal = 0 then '700000' else '700210' end,
stock.s_comptea = case when inserted.s_compte_manuel = 1 then stock.s_comptev when inserted. articlenormal = 0 then '604000' else '604210' end,
stock.s_etiq = case when stock.s_type_etiq = 'CARTON' then '3' when stock.s_type_etiq = 'COLLANTE' then '2' else '1' end,
stock.s_cle3 = inserted.s_condit_a
from stock inner join inserted on inserted.s_id = stock.s_id
end
Au lieu de 3 updates sur la table stock, nous n’avons plus qu’un seul update pour l’ensemble des champs concernés. Ceci va permettre d'éviter des appels successifs du trigger.
On pourrait aller plus loin en faisant ces tests en plus et en adaptant la requête avec les champs concernés (pour éviter les "case when ... then ... else ... end") : if update(s_taux_tva) and update(s_type_etiq) and update(s_condit_a) ...
if update(s_taux_tva) and update(s_type_etiq) and not update(s_condit_a) ...
if update(s_taux_tva) and not update(s_type_etiq) and update(s_condit_a) ...
if not update(s_taux_tva) and update(s_type_etiq) and update(s_condit_a) ...
if update(s_taux_tva) and not update(s_type_etiq) and not update(s_condit_a) ...
if not update(s_taux_tva) and update(s_type_etiq) and not update(s_condit_a) ...
if not update(s_taux_tva) and not update(s_type_etiq) and update(s_condit_a) ...
Spécificités de la table DISPO