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

Oracle DBMS - Leia uma tabela antes de processar Atualizando em um gatilho AFTER - tabela mutante


Apenas para esclarecer, a exceção da tabela mutante é lançada porque você está tentando ler as rooms table em sua função, não porque você está tentando ler as properties tabela. Como você tem um acionador em nível de linha em rooms , isso significa que as rooms table está no meio de uma alteração quando o gatilho em nível de linha está sendo acionado e pode estar em um estado inconsistente. O Oracle impede que você consulte as rooms tabela nessa situação porque os resultados não são necessariamente determinísticos ou reprodutíveis.

Se você criou um gatilho de nível de instrução (removendo o FOR EACH ROW ) e colocar sua lógica lá, você não encontrará mais uma exceção de tabela mutante porque as rooms tabela não estaria mais em um estado inconsistente. Um gatilho de nível de instrução, no entanto, não é capaz de ver quais linhas foram modificadas. Isso significaria que você precisaria examinar todas as propriedades para ver quais valores de status devem ser ajustados. Isso não vai ser particularmente eficiente.

Ao custo de complexidade adicional, você pode melhorar o desempenho capturando quais propriedades foram alteradas em um gatilho de nível de linha e, em seguida, referindo-se a elas em um gatilho de nível de instrução. Isso geralmente requer três gatilhos e um pacote, o que obviamente aumenta o número de peças móveis substancialmente (se você estiver no 11.2, você pode usar um gatilho composto com três gatilhos de componentes que simplifica um pouco as coisas, eliminando a necessidade de usar o pacote) . Isso seria algo como
CREATE OR REPLACE PACKAGE trigger_collections
AS
  TYPE modified_property_tbl IS TABLE OF properties.property_id%type;
  g_modified_properties modified_property_tbl;
END;

-- Initialize the collection in a before statement trigger just in case
-- there were values there from a prior run
CREATE OR REPLACE TRIGGER trg_initialize_mod_prop_coll
  BEFORE INSERT OR UPDATE ON rooms
BEGIN
  trigger_collections.g_modified_properties := trigger_collections.modified_property_tbl();
END;

-- Put the property_id of the modified row in the collection
CREATE OR REPLACE TRIGGER trg_populate_mod_prop_coll
  AFTER INSERT OR UPDATE ON rooms
  FOR EACH ROW
BEGIN
  trigger_collections.g_modified_properties.extend();
  trigger_collections.g_modified_properties( trigger_collections.g_modified_properties.count + 1 ) := :new.property_id;
END;

CREATE OR REPLACE TRIGGER trg_process_mod_prop_coll
  AFTER INSERT OR UPDATE ON rooms
BEGIN
  FOR p IN 1 .. trigger_collections.g_modified_properties.count
  LOOP
    IF prop_vacancy_query( trigger_collections.g_modified_properties(i) ) = 0 
    THEN
      ...
END;