Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como criar um gatilho de linha PL/SQL que valida uma coluna de outra tabela


Existem vários problemas com o seu gatilho. Vamos começar com o 'relacionamento' entre uma instrução select e o código restante. Neste caso em particular, o select.. e o if...end_if (no momento, suponha que seu select realmente funcione, ele não funciona, mas apenas assume). Agora concentre-se na cláusula WHERE.
SELECT SUPPLIER.TRUSTED_SUPPLIER
    INTO TRUST
    ...
    WHERE SUPPLIER.TRUSTED_SUPPLIER = 'YES';

IF TRUST = 'NO' THEN ...

Como seu select retorna SOMENTE YES, a instrução if nunca será True. Portanto, a exceção do aplicativo nunca pode ser levantada. Agora, quais são os problemas com o select .
Bem, primeiro você está acessando a tabela na qual o gatilho é disparado. Embora em alguns casos você possa se safar, mas geralmente resulta em um ORA -04091:a tabela está mudando, o gatilho/função pode não vê-la . É inútil sempre evitar fazer referência à tabela de acionamento por completo. Você faz referência aos dados da tabela com os pseudo registros :NEW e/ou :OLD. Em segundo lugar, sua consulta não está fazendo o que você pensa. Diz

No entanto, a cláusula INTO exige que a instrução retorne exatamente 1 linha . Mais de 1 linha resulta na exceção e 0 linha resulta em um no data found exceção.
Finalmente, há um problema com a raise_application_error statement . Se fosse executado, geraria um argumento de número... está fora do intervalo exceção. O primeiro parâmetro deve estar entre -20999 a -20000 (número negativo). Então, como é o resultado:
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;
/

NOTAS:
Não use o tipo de dados VARCHAR. É permitido, mas a Oracle não recomenda. Significa que eles estão se reservando o direito de mudar o que faz a qualquer momento. Em vez disso, use o VARCHAR2 recomendado.
Eu mudo o gatilho para disparar em Insert ou Update. Se acionado em Inserir, apenas alguém PODE alterar o nome_do_fornecedor para fazer referência a um fornecedor não confiável e tudo ficará bem.