sql >> Databáze >  >> RDS >> Oracle

Jak vytvořit spouštěč řádku PL/SQL, který ověřuje sloupec z jiné tabulky

S vaším spouštěčem je několik problémů. Začněme „vztahem“ mezi příkazem select a zbývajícím kódem. V tomto konkrétním případě select.. a if...end_if (pro tuto chvíli předpokládejme, že váš výběr skutečně funguje, ne, ale pouze předpokládá). Nyní se soustřeďte na klauzuli WHERE.

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

IF TRUST = 'NO' THEN ...

Protože váš select vrací POUZE YES, příkaz if nikdy nebude mít hodnotu True. Proto výjimka aplikace nemůže být nikdy vyvolána. Nyní, jaké jsou problémy s select .
Nejdřív se dostáváte k tabulce, na kterou se spustí spoušť. I když v některých případech vám to projde, ale obvykle to vede k ORA -04091:tabulka mutuje, spouštěč/funkce ji nemusí vidět . Je zbytečné se vždy úplně vyhýbat odkazování na tabulku spouštění. Na data tabulky odkazujete pseudo záznamy :NEW a/nebo :OLD. Za druhé, váš dotaz nedělá to, co si myslíte, že je. Říká to

Klauzule INTO však vyžaduje, aby příkaz vrátil přesně 1 řádek . Více než 1 řádek vede k výjimce a 0 řádků vede k no data found výjimka.
Nakonec došlo k problému s raise_application_error statement . Pokud by byla provedena, vyvolalo by to argument čísla...je mimo rozsah výjimka. První parametr musí být v rozmezí -20999 až -20000 (záporné číslo). Jak tedy vypadá výsledek:

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;
/

POZNÁMKY:
NEPOUŽÍVEJTE datový typ VARCHAR. Je to povoleno, ale Oracle to nedoporučuje. Znamená to, že si vyhrazují právo kdykoli změnit to, co dělá. Místo toho použijte doporučený VARCHAR2.
Změním spouštěč tak, aby se spouštěl při vložení nebo aktualizaci. Pokud se spustí na Insert, pouze někdo MŮŽE změnit jméno dodavatele tak, aby odkazovalo na nedůvěryhodného dodavatele a vše by bylo v pořádku.



  1. Google AppEngine ImportError:dynamický modul nedefinuje funkci init (init_mysql)

  2. Vyberte řádky závislé na počtu z více tabulek se sjednocením

  3. Vícenásobné vložení PDO

  4. Význam id =LAST_INSERT_ID(id)