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

Opdater Trigger PL/SQL Oracle

Prøv en sammensat trigger:

CREATE OR REPLACE TRIGGER compound_trigger_name
FOR  INSERT OR UPDATE OF salary ON treballa
COMPOUND TRIGGER

  TYPE Departments_t   IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
  Departments          Departments_t;

     BEFORE EACH ROW IS
     BEGIN
        -- collect updated or inserted departments 
        Departments( :new.department ) := :new.department;
     END BEFORE EACH ROW;

     AFTER STATEMENT IS
        sum_sal NUMBER;
     BEGIN
      -- for each updated department check the restriction
      FOR dept IN Departments.FIRST .. Departments.LAST
      LOOP
         SELECT sum(salary) INTO sum_sal FROM treballa WHERE department = dept;
         IF sum_sal > 1000 THEN
            raise_application_error(-20123, 'The total salary for department '||dept||' cannot exceed 1000');
         END IF;
      END LOOP;
     END AFTER STATEMENT;

END compound_trigger_name;
/

========REDIGER - et par spørgsmål og svar ===========

Sp:Hvorfor opstår der en mutationstabelfejl?
A:Dette er beskrevet i dokumentationen:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#g1699708

Sp:hvordan undgår man en mutationstabelfejl?
A:Dokumentationen anbefaler brugen af ​​en coumpound-trigger, se denne:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CHDFEBFJ

Sp:Hvad er en sammensat trigger, og hvordan virker den?
A:Dette er et stort emne, se venligst dokumentationen her:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CIHEFGFD

Kort sagt:dette er en særlig slags trigger, der gør det muligt at kombinere fire typer separate triggere:BEFORE statement , BEFORE-for each row , AFTER for each row og AFTER statament til en én-erklæring. Det gør det lettere at implementere nogle scenarier, hvor der er behov for at overføre nogle data fra en trigger til en anden. Læs venligst ovenstående link for flere detaljer.

Sp:Men hvad gør "Departments( :new.department ) := :new.department; ?
A:Denne erklæring gemmer et afdelingsnummer i et associativt array.

Dette array er deklareret i en deklarativ del af den sammensatte trigger:

  TYPE Departments_t   IS TABLE OF treballa.department%TYPE INDEX BY varchar2(100);
  Departments          Departments_t;

Dokumentationen relateret til de sammensatte triggere siger, at:http ://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CIHJBEFE

Ovenstående betyder, at Departments variabel initialiseres kun én gang i begyndelsen af ​​hele behandlingen, lige efter at triggeren udløses. "Udgivelsesudsagns varighed" betyder, at denne variabel ødelægges, efter at triggeren er færdig.

Denne erklæring:Departments( :new.department ) := :new.department; gemmer et afdelingsnummer i det associative array. Det er i BEFORE EACH ROW sektion, så udføres den for hver række, der opdateres (eller indsættes) af update/insert-sætningen.

:new og :old er pseudorecords, mere om dem kan du finde her: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS99955
Kort sagt::new.department henter en ny værdi for department kolonne- for en aktuelt opdateret række (opdateret værdi - EFTER opdateringen), mens :old.department giver en gammel værdi af denne kolonne (FØR opdateringen).

Denne samling bruges senere i AFTER STATEMENT , når triggerne vælger alle opdaterede afdelinger (i en FOR-LOOP), for hver afdeling fyrer SELECT SUM(salary) ... og kontrollerer derefter, om denne sum er mindre end 1000

Overvej en simpel opdatering:UPDATE treballa SET salary = salary + 10 . Dette er en enkelt opdateringserklæring, men ændrer mange rækker på én gang. Rækkefølgen for udførelse af vores trigger er som følger:

  1. Opdateringsstatementet udløses:UPDATE treballa SET salary = salary + 10
  2. Den deklarative sektion af triggeren udføres, dvs.:Departments variabel initialiseres
  3. BEFORE EACH ROW sektion udføres, separat for hver opdateret række - så mange gange som der er rækker, der skal opdateres. På dette sted samler vi alle afdelinger fra ændrede rækker.
  4. AFTER STATEMENT afsnit udføres. På dette tidspunkt er tabellen allerede opdateret - alle rækker har allerede nye, opdaterede lønninger. Vi gennemgår afdelinger gemt i Departments og for hver enkelt tjekker vi, om summen af ​​lønninger er mindre eller lig med 1000. Hvis denne sum er> 1000 for nogen af ​​disse afdelinger, bliver der smidt en fejl, og hele opdateringen afbrydes og rulles tilbage. Ellers afsluttes triggeren, og opdateringen er færdig (men du skal alligevel foretage disse ændringer).

Sp:Hvad er et associativt array, og hvorfor bruges netop denne form for samling i stedet for andre samlinger (en varray eller en indlejret tabel)?
Sv:PL/SQL-samlinger er et stort emne. Følg dette link for at lære dem at kende:http:// docs.oracle.com/cd/E11882_01/appdev.112/e25519/composites.htm#LNPLS005

Kort sagt - Associativ array (eller indeks-efter tabel) er som et kort i java (hashmap, trækort osv.) - det er et sæt nøgleværdi-par, og hver nøgle er unik . Du kan sætte den samme nøgle mange gange til dette array (med forskellige værdier), men denne nøgle vil kun blive gemt én gang - den er unik.
Jeg har brugt den til at få et unikt sæt af afdelinger.
Overvej vores opdateringseksempel igen:UPDATE treballa SET salary = salary + 10 - denne kommando berører hundredvis af rækker, der har samme afdeling. Jeg vil ikke have en samling med den samme afdeling duplikeret 100 gange, jeg har brug for et unikt sæt afdelinger, og jeg vil udføre vores forespørgsel SELECT sum()... kun én gang for hver afdeling, ikke 100 gange. Ved hjælp af det sssociative array sker det automatisk - jeg får et unikt sæt af afdelinger.




  1. mysqld_safe Directory '/var/run/mysqld' for UNIX socket fil eksisterer ikke

  2. JDBC batch operationsforståelse

  3. Datetime BETWEEN-sætningen virker ikke i SQL Server

  4. Registrer nyt servernavn i SQL Management Studio