U bevindt zich nu op een technische pagina over de software Mercator. Deze pagina bevat specifieke informatie die bestemd is voor professionals van de software Mercator. Wenst u naar algemenere informatie over Mercator door te gaan?


   Deze vraag niet meer stellen

Optimaal schrijven van triggers

0000003024     -      17-01-2022

Het slechte gebruik van triggers in foute omstandigheden kan de prestaties van de SQL-server en dus van Mercator ernstig aantasten.
Over het algemeen moet men zeer voorzichtig zijn bij het plaatsen van een trigger.

Hier zijn enkele regels die u moet volgen bij het schrijven van "aangepaste" triggers :

  • U mag een standaard trigger nooit wijzigen, deze kan tijdens een update opnieuw worden geïnstalleerd door Mercator.
  • Een trigger kan betrekking hebben op meerdere records. Werk dus altijd met inserted/deleted tabellen, nooit met scalaire variabelen.
    Voorbeeld :
    update stock
            set stock.s_cle3 = inserted.s_condit_a
            from stock inner join inserted on inserted.s_id = stock.s_id


  • Standaard kan er voor elke bewerking een trigger zijn (insert, update, delete). Als het nodig is om andere triggers toe te voegen moeten deze gegroepeerd worden zodat er slechts één (maximaal) per bewerking is.
    Het is ideaal om, indien mogelijk, de verschillende operaties in één trigger te groeperen; in het bijzonder de triggers "on insert" en "on update". Om te weten of u aan het wijzigen bent, moet u testen of er een record in de tabel deleted staat.
    Voorbeeld:
    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


  • U kan de syntax "if update (veldnaam)" gebruiken om deze code alleen uit te voeren als de record echt is gewijzigd (zelfs in het geval van een insert).
    Dit is niet toepasbaar bij delete.
    Voorbeeld :
    if update(s_cle2)
    Dit helpt ook om een recursie van de triggers te voorkomen. Dit kan gebeuren wanneer de velden (bijvoorbeeld in de STOCK-tabel) worden bijgewerkt door een trigger, zelf een andere trigger op dezelfde tabel activeren (die een van de velden zou kunnen bijwerken die door de eerste trigger worden beheerd). Er ontstaat dan een oneindige lus. 

  • Gezien het belang van een trigger met betrekking tot de prestaties moeten we niet proberen een "mooie" trigger te maken die makkelijk te lezen is. Het is dus noodzakelijk om deze zo veel mogelijk te optimaliseren om zo een klein mogelijk effect op de prestaties te hebben.
    Voorbeeld :
    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
    wordt :
    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
    
    In plaats van 3 updates op de STOCK-tabel hebben we maar één update voor alle betrokken velden. Dit zal het mogelijk maken om opeenvolgende oproepen van de trigger te vermijden. 

    We zouden verder kunnen gaan door deze aanvullende testen uit te voeren en de zoekopdracht aan te passen met de betreffende velden (om te voorkomen dat "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) ...

 


 

Specifieke kenmerken van de DISPO-tabel
  • Het komt vaak voor dat de trigger wordt geschreven alsof alle lijnen (en dus alle magazijnen) van een artikel zijn ingevoegd. We zien daarom vaak bijvoorbeeld :
    sum(dispo-qv_3) from inserted
    Dit is onjuist : Inserted bevat alleen de gewijzigde lijn(en) ; daarom komt bij het valideren van een document uit het commercieel beheer slechts één lijn overeen met het magazijn.

  • Een veel voorkomende fout is het plaatsen van een trigger op DISPO die een veld van de STOCK-tabel voedt zonder het ID van het magazijn te testen. Dit werkt zolang de fiche maar één magazijn heeft. Maar de dag dat een tweede magazijn wordt gedefinieerd, ontvangen we daarom willekeurig de waarde van magazijn 1 of de waarde van magazijn 2, afhankelijk van het laatst bewogen magazijn.
    Dus, zelfs voor een fiche met slechts één magazijn, moet u het magazijn testen waarvan de waarde moet doorgegeven worden in de STOCK-tabel.