sql >> Databasteknik >  >> RDS >> Oracle

Hur man skapar en PL/SQL-radutlösare som validerar en kolumn från en annan tabell

Det finns flera problem med din trigger. Låt oss börja med 'förhållandet' mellan en select-sats och återstående kod. I det här specifika fallet select.. och if...end_if (antag för tillfället att ditt val faktiskt fungerar, det gör det inte utan antar bara). Koncentrera dig nu på WHERE-satsen.

SELECT SUPPLIER.TRUSTED_SUPPLIER
    INTO TRUST
    ...
    WHERE SUPPLIER.TRUSTED_SUPPLIER = 'YES';

IF TRUST = 'NO' THEN ...

Eftersom ditt val ENDAST returnerar JA kommer if-satsen aldrig att vara Sann. Därför kan tillämpningsundantaget aldrig tas upp. Vad är nu problemen med select .
Tja, först kommer du åt bordet som utlösaren utlöses på. Även om du i vissa fall kan komma undan med det, men vanligtvis resulterar det i en ORA -04091:Tabell muterar, trigger/funktion kanske inte ser den . Det är busat att alltid undvika att referera till utlösningstabellen helt och hållet. Du refererar till tabelldata med pseudoposterna :NEW och/eller :OLD. För det andra gör din fråga inte vad du tror att den är. Det står

Men INTO-satsen kräver att satsen returnerar exakt 1 rad . Mer än 1 rad resulterar i undantaget och 0 rader resulterar i no data found undantag.
Äntligen finns det ett problem med raise_application_error statement . Om det kördes skulle det skapa ett talargument...är utanför intervallet undantag. Den första parametern måste vara mellan -20999 och -20000 (negativt tal). Så hur ser resultatet ut:

create or replace trigger verify_supplier_trust
before insert or update on product
for each row 
declare 
    trust varchar2(3);

begin
    select supplier.trusted_supplier
      into trust
      from supplier 
     where supplier.company_name = :new.supplier_name
       and supplier.trusted_supplier = 'YES';
exception
   when no_data_found then 
        raise_application_error(-20001, 'supplier not trusted');
end;
/

ANMÄRKNINGAR:
Använd inte datatyp VARCHAR. Det är tillåtet men Oracle avråder från det. Betyder att de förbehåller sig rätten att ändra vad den gör när som helst. Använd den rekommenderade VARCHAR2 istället.
Jag ändrar utlösaren till att aktiveras på antingen Insert eller Update. Om den aktiveras på Insert KAN bara någon ändra leverantörsnamnet för att referera till en icke-pålitlig leverantör och allt skulle vara bra.



  1. Hur kontrollerar man om alla fält är unika i Oracle?

  2. Dubbelkontroll mellan DATABASE och DATABLE

  3. Uppdatera ersätt semikolon i SQL får syntaxfel

  4. MYSQL-fråga - få rader där priset ändras