sql >> Databasteknik >  >> RDS >> Oracle

Oracle - Problem med att skapa trigger som uppdaterar en annan tabell

Några problem i ingen speciell ordning.

Först måste du använda :new i kroppen av en utlösare på radnivå och :old för att referera till nya och gamla register. Den ledande kolon är nödvändig. Så din WHERE klausul skulle behöva vara

WHERE PROJECTID = :new.PROJECTID

För det andra, om du kör din CREATE TRIGGER i SQL*Plus kan du få en lista över fel och varningar med hjälp av SHOW ERRORS kommando, dvs.

SQL> show errors

Du kan också fråga DBA_ERRORS tabell (eller ALL_ERRORS eller USER_ERRORS beroende på din privilegienivå) men det är inget du normalt behöver ta till.

För det tredje, förutsatt att syntaxfelen korrigeras, kommer du att få en mutering tabellfel om du använder denna logik. En radnivåutlösare i tabell A (TPM_TRAININGPLAN i det här fallet) kan inte fråga tabell A eftersom tabellen kan vara i ett inkonsekvent tillstånd. Du kan kringgå det, som Tim visar i sin artikel, genom att skapa ett paket med en samling, initiera den samlingen i en before-utlösare, fylla i data i samlingen i en utlösare på radnivå och sedan bearbeta de modifierade raderna i en efter uttalande trigger. Det är dock en anständig mängd komplexitet att lägga till i systemet, eftersom du måste hantera flera olika objekt.

Generellt sett är det bättre för dig att implementera denna logik som en del av vilket API du än använder för att manipulera TPM_TRAININGPLAN tabell. Om det är en lagrad procedur är det mycket mer meningsfullt att använda logiken för att uppdatera TPM_PROJECT i den lagrade proceduren snarare än att sätta den i en trigger. Det är notoriskt smärtsamt att försöka felsöka en applikation som har mycket logik inbäddad i triggers eftersom det gör det mycket svårt för utvecklare att följa exakt vilka operationer som utförs. Alternativt kan du ta bort TRAININGDELIVERYSTART kolumn från TPM_PROJECT tabell och bara beräkna det lägsta startdatumet vid körning.

För det fjärde, om din trigger aktiveras vid infogning, uppdatering och borttagning, kan du inte bara referera till :new värden. :new är giltigt för infogningar och uppdateringar men det kommer att vara NULL om du gör en radering. :old är giltig för raderingar och uppdateringar men kommer att vara NULL om du gör en infogning. Det betyder att du förmodligen behöver ha logik i linje med (med hänvisning till Tims paketlö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. Är MySQL Connector/JDBC tråd säker?

  2. Hur man inaktiverar förberedda uttalanden i heroku med postgres databas

  3. Slå samman två tabeller med hjälp av id och ättlingar från trädliknande bord

  4. Skapa en utlösare som uppdaterar en kolumn i en tabell när en kolumn i en annan tabell uppdateras