MainframeSupports
tip uge 45/2002:

I version 6 af DB2 blev det endelig muligt at lave triggers på DB2-tabeller. Nu står version 8 snart for døren, så mon ikke det er på tide med lidt omtale af denne forholdsvis nye mulighed. Dette tip er en simpel introduktion til triggers og vil kun berøre emnet nok til at sætte dig i stand til at lave dine første simple triggers til validering af data.

Det gode ved triggers i mine øjne er, at de kan aktiveres på eksisterende tabeller og dermed indføre nye valideringer, som ikke behøver gælde for de eksisterende rækker i tabellen. De er altså ikke nær så skrappe som RI og de såkaldte table constraints. Og de er også lette at pille af igen. Man kan desuden styre om en trigger skal gælde for insert, update eller delete, så det er muligt at foretage forskellige valideringer afhængig af situationen.

Her følger et eksempel på en simpel såkaldt "before trigger", der foretager lidt validering af de data, der forsøges insert'et på en tabel. En "before trigger" aktiveres før selve operationen (i dette tilfælde en insert) udføres:

CREATE TRIGGER mycheck NO CASCADE BEFORE
INSERT ON mytable REFERENCING NEW AS mt
FOR EACH ROW MODE DB2SQL WHEN
( NOT EXISTS (SELECT 0 FROM mycodes WHERE mycode = mt.mycol1)
  AND NOT mt.mycol2 BETWEEN 1 AND 9
) SIGNAL SQLSTATE '75001' ('Columns mycol1 or mycol2 invalid')
;

Denne trigger bliver oprettet under navnet MYCHECK. Som creator benyttes her det aktuelle SQLID, og i øvrigt hedder det ikke en creator, men et schema. Navne på triggers kan i øvrigt kun være 8 tegn lange (sikket noget skod). NO CASCADE BEFORE angiver, at det er en "before trigger". INSERT angiver, at triggeren aktives ved insert på den angivne tabel. Man kan kun angive en operation pr. trigger. Man kan altså ikke lave en trigger, der er den samme for eksempelvis INSERT og UPDATE, men er nødt til at lave to. REFERENCING NEW AS angiver, at kolonnerne i den nye række får det efterfølgende navn som correlation-id. Ved en update trigger kan man også angive REFERENCING OLD AS og dermed sammenholde værdier fra den eksisterende række med den nye række. FOR EACH ROW MODE DB2SQL skal angives, når det er en "before trigger".

WHEN angiver i parentes den validering, der skal udføres. I dette tilfælde udføres der en kontrol mod en tabel (svarer til en RI kontrol) og værdisættet for en anden kolonne kontrolleres. Hvis valideringen er sand, så udføres SQL-kaldet lige efter højreparentesen, der afslutter WHEN. Der kan kun angives en WHEN i samme trigger. Til gengæld kan der udføres mange SQL-kald. Man skal i så fald skrive BEGIN ATOMIC før det første SQL-kald, afslutte hvert SQL-kald med ; og skrive END efter det sidste ;. Nu er der det "sjove" ved denne konstruktion, at en masse af de værktøjer, der kan udføre dynamisk SQL, sværger til ; som skilletegn mellem hvert SQL-kald. Det volder selvfølgelig problemer for CREATE TRIGGER. Hvis ellers SPUFI er installeret i en version 6 eller 7 udgave, så kan du vælge nyt skilletegn, så du undgår problemer. Jeg vil også råde dig til at skrive END med stort, da der åbenbart har indsneget sig en fejl i SQL parseren. Da jeg prøvede med småt fik jeg en SQL fejl, som efter megen prøven frem og tilbage forsvandt, når jeg skrev END med stort.

SIGNAL SQLSTATE er et SQL-kald, der kun kan benyttes i triggers. Hvis det eksekveres, så sættes returkoden fra det SQL-kald, der satte gang i triggeren, til sqlcode -438. Feltet SQLERRMC i SQLCA vil indeholde teksten i parentesen. SQLERRMC er en del af feltet SQLERRM, som også består af SQLERRML, som er et to bytes længdefelt, der angiver, hvor mange bytes af SQLERRMC, der er udfyldt. Feltet SQLSTATE i SQLCA vil indeholde den angivne SQLSTATE. Man kan i øvrigt ikke angive hvad som helst som SQLSTATE. Her er der hjælp at hente i SQL reference manualen.

Jeg vil varmt anbefale, at du prøver forskellige ting af med triggers før du kaster dig ud i produktionsanvendelse. Det er i øvrigt ikke sikkert, at din installation har fået indført migreringsprocedurer eller andet godt for triggers endnu. Det kan godt komme til at volde vanskeligheder. Hvis du vil se om der er oprettet nogle andre triggers på dit DB2-system, så er systemtabellen SYSIBM.SYSTRIGGERS det helt rigtige sted at kigge. I tabellen kan man se hele teksten til de registrerede CREATE TRIGGER SQL-kald.

Forrige danske tip        Last tip in english        Tip oversigten