Oracle
 sql >> Datenbank >  >> RDS >> Oracle

So erstellen Sie einen PL/SQL-Zeilentrigger, der eine Spalte aus einer anderen Tabelle validiert

Es gibt mehrere Probleme mit Ihrem Trigger. Beginnen wir mit der „Beziehung“ zwischen einer select-Anweisung und dem verbleibenden Code. In diesem speziellen Fall select.. und das if...end_if (Im Moment gehen Sie davon aus, dass Ihre Auswahl tatsächlich funktioniert, es funktioniert nicht, sondern geht nur davon aus). Konzentrieren Sie sich jetzt auf die WHERE-Klausel.

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

IF TRUST = 'NO' THEN ...

Da Ihre Auswahl NUR JA zurückgibt, wird die if-Anweisung niemals wahr sein. Daher kann die Anwendungsausnahme nie ausgelöst werden. Nun, was sind die Probleme mit select .
Zunächst greifen Sie auf die Tabelle zu, auf die der Trigger ausgelöst wird. Während Sie in einigen Fällen damit durchkommen, führt dies normalerweise zu einem ORA -04091:Tabelle mutiert, Trigger/Funktion sieht sie möglicherweise nicht . Es ist fehlgeschlagen, immer zu vermeiden, die auslösende Tabelle insgesamt zu referenzieren. Mit den Pseudo-Records :NEW und/oder :OLD referenzieren Sie die Tabellendaten. Zweitens macht Ihre Abfrage nicht das, was Sie denken. Es heißt

Die INTO-Klausel erfordert jedoch, dass die Anweisung genau 1 Zeile zurückgibt . Mehr als 1 Zeile führt zu einer Ausnahme und 0 Zeilen führen zu einem no data found Ausnahme.
Schließlich gibt es ein Problem mit der raise_application_error statement . Wenn es ausgeführt würde, würde es ein number argument...is out of range auslösen Ausnahme. Der erste Parameter muss zwischen -20999 und -20000 liegen (negative Zahl). Wie sieht das Ergebnis also aus:

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

HINWEISE:
Verwenden Sie nicht den Datentyp VARCHAR. Es ist erlaubt, aber Oracle rät davon ab. Bedeutet, dass sie sich das Recht vorbehalten, ihre Funktionsweise jederzeit zu ändern. Verwenden Sie stattdessen das empfohlene VARCHAR2.
Ich ändere den Trigger so, dass er entweder beim Einfügen oder beim Aktualisieren ausgelöst wird. Wenn auf Einfügen gefeuert wird, KANN nur jemand den Lieferantennamen ändern, um auf einen nicht vertrauenswürdigen Lieferanten zu verweisen, und alles wäre in Ordnung.