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

Oracle - Problema ao criar trigger que atualiza outra tabela


Alguns problemas em nenhuma ordem específica.

Primeiro, no corpo de um gatilho em nível de linha, você precisa usar :new e :old para referenciar os registros novos e antigos. Os dois pontos principais são necessários. Portanto, seu WHERE cláusula precisaria ser
WHERE PROJECTID = :new.PROJECTID

Segundo, se você estiver executando seu CREATE TRIGGER no SQL*Plus, você pode obter uma lista dos erros e avisos usando o SHOW ERRORS comando, ou seja
SQL> show errors

Você também pode consultar o DBA_ERRORS tabela (ou ALL_ERRORS ou USER_ERRORS dependendo do seu nível de privilégio), mas isso não é algo que você normalmente precisa recorrer.

Terceiro, supondo que os erros de sintaxe sejam corrigidos, você obterá uma mutating erro de tabela se você usar essa lógica. Um gatilho de nível de linha na tabela A (TPM_TRAININGPLAN neste caso) não pode consultar a tabela A porque a tabela pode estar em um estado inconsistente. Você pode contornar isso, como Tim mostra em seu artigo, criando um pacote com uma coleção, inicializando essa coleção em um gatilho de instrução antes, preenchendo os dados da coleção em um gatilho de nível de linha e processando as linhas modificadas em um gatilho de instrução after. Essa é uma quantidade razoável de complexidade para adicionar ao sistema, no entanto, já que você terá que gerenciar vários objetos diferentes.

Geralmente, seria melhor implementar essa lógica como parte de qualquer API que você usa para manipular o TPM_TRAININGPLAN tabela. Se for um procedimento armazenado, faz muito mais sentido colocar a lógica para atualizar TPM_PROJECT nesse procedimento armazenado em vez de colocá-lo em um gatilho. É notoriamente doloroso tentar depurar um aplicativo que tem muita lógica embutida em gatilhos porque isso torna muito difícil para os desenvolvedores seguirem exatamente quais operações estão sendo executadas. Como alternativa, você pode remover o TRAININGDELIVERYSTART coluna de TPM_PROJECT tabela e apenas calcular a data de início mínima em tempo de execução.

Quarto, se o seu acionador for acionado em inserções, atualizações e exclusões, você não poderá simplesmente referenciar :new valores. :new é válido para inserções e atualizações, mas será NULL se você estiver fazendo uma exclusão. :old é válido para exclusões e atualizações, mas será NULL se você estiver fazendo uma inserção. Isso significa que você provavelmente precisa ter lógica ao longo das linhas de (referenciando a solução de pacote de Tim)
BEGIN
  IF inserting 
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
  ELSIF updating
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
  ELSIF deleting
  THEN
    trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
  END IF;
END;