Полтавский П. В., разработчик ПО, компания
В процессе эксплуатации автоматизированной системы учета операций с ценными бумагами возникла необходимость создания таблицы для хранения детальной информации (истории сделок). Для её заполнения был разработан механизм, реализуемый набором триггеров БД и серверных пакетных процедур, вызываемых из триггеров. Но при тестировании данного механизма возникла следующая ситуация: при срабатывании триггера вызываемая им серверная процедура запрашивает данные из таблицы, на которой создан триггер. В результате возникает ошибка мутации:
ORA-04091: table <имя_таблицы> is mutating, trigger/function may not see it
(описание этого явления выходит за рамки данной статьи). Для решения проблемы были использованы следующие методы:
При вставке или изменении записи из таблицы документов выполняется процедура инициализации глобальной переменной пакета значением столбца внутреннего идентификатора записи сделки. Это происходит при срабатывании следующего триггера (FOR EACH ROW trigger):
CREATE OR REPLACE TRIGGER DB_DOC_T1 after insert or update on DB_DOC FOR EACH ROW
begin if (inserting or updating) then DP_STNDS.Set_Id_Deal(:new.id_deal); else DP_STNDS.Set_Id_Deal(:old.id_deal); end if; end;
Пакетная процедура DP_STNDS.Set_Id_Deal и функция DP_STNDS.Get_Id_Deal чтения инициализированного значения пакетной переменной определяются следующим образом: … PROCEDURE Set_Id_deal(p_id_deal in db_doc.id_deal%type) is begin dp_id_deal:= p_id_deal; end;
FUNCTION Get_Id_Deal_No RETURN dp_id_deal db_doc.id_deal%type is begin return dp_id_deal ; end; …
Переменная dp_id_deal является глобальной переменной пакета DP_STNDS и объявляется в теле пакета:
CREATE OR REPLACE PACKAGE BODY DP_STNDS AS -- Переменные пакета dp_id_deal db_doc.id_deal%type; … END PACKAGE BODY DP_STNDS;