sql >> Database teknologi >  >> RDS >> Oracle

Oracle - Problem med at oprette trigger, der opdaterer en anden tabel

Et par problemer i nogen bestemt rækkefølge.

For det første skal du bruge :new i brødteksten af ​​en trigger på rækkeniveau og :old at referere til de nye og gamle optegnelser. Den ledende kolon er nødvendig. Så din WHERE klausul skulle være

WHERE PROJECTID = :new.PROJECTID

For det andet, hvis du kører din CREATE TRIGGER i SQL*Plus kan du få en liste over fejl og advarsler ved hjælp af SHOW ERRORS kommando, dvs.

SQL> show errors

Du kan også forespørge på DBA_ERRORS tabel (eller ALL_ERRORS eller USER_ERRORS afhængigt af dit privilegieniveau), men det er ikke noget, du normalt behøver at ty til.

For det tredje, forudsat at syntaksfejlene bliver rettet, vil du få en mutering tabelfejl hvis du bruger denne logik. En udløser på rækkeniveau i tabel A (TPM_TRAININGPLAN i dette tilfælde) kan ikke forespørge tabel A, fordi tabellen kan være i en inkonsistent tilstand. Du kan omgå det, som Tim viser i sin artikel, ved at oprette en pakke med en samling, initialisere den samling i en før-sætningsudløser, udfylde dataene i samlingen i en trigger på rækkeniveau og derefter behandle de ændrede rækker i en efterudsagnsudløser. Det er dog en anstændig mængde kompleksitet at tilføje til systemet, da du bliver nødt til at administrere flere forskellige objekter.

Generelt ville du være bedre stillet at implementere denne logik som en del af den API, du bruger til at manipulere TPM_TRAININGPLAN bord. Hvis det er en lagret procedure, giver det meget mere mening at sætte logikken til at opdatere TPM_PROJECT i den lagrede procedure i stedet for at sætte den i en trigger. Det er notorisk smertefuldt at forsøge at fejlsøge en applikation, der har en masse logik indlejret i triggere, fordi det gør det meget vanskeligt for udviklere at følge præcis, hvilke operationer der udføres. Alternativt kan du fjerne TRAININGDELIVERYSTART kolonne fra TPM_PROJECT tabel og udregn den mindste startdato ved kørsel.

For det fjerde, hvis din trigger udløses ved indsættelser, opdateringer og sletninger, kan du ikke blot henvise til :new værdier. :new er gyldig for indsættelser og opdateringer, men det vil være NULL, hvis du sletter. :old er gyldig til sletninger og opdateringer, men vil være NULL, hvis du laver en indsættelse. Det betyder, at du sandsynligvis skal have logik i retning af (med henvisning til Tims pakkeløsning)

BEGIN
  IF inserting 
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
  ELSIF updating
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
  ELSIF deleting
  THEN
    trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
  END IF;
END;


  1. Send array i Mysql-forespørgsel med nodejs

  2. Android SQLiteDB er ikke færdig med at tilføje værdier

  3. tjek for duplikerede data før indsættelse

  4. jdbc batch ydeevne