Возможно, стоит выяснить, почему существует правило «без триггеров».
Есть много хороших аргументов против триггеров - особенно о включении бизнес-правил в триггеры - но протоколирование обычно считается хорошим примером для их использования.
Стоит также взглянуть на встроенный Oracleуправление версиями таблицы (которая записывает строку для каждого обновления) - это сохраняет форму истории в соответствии с текущей формой таблицы.Он не дает вам историю «что изменилось», но, вероятно, лучше делать «что изменилось» в тот момент, когда вы смотрите историю, а не добавлять стоимость на каждое обновление.
Единственный способ сделать что-то наподобие того, что вы хотите - динамический доступ к свойству% ROWTYPE, - это поместить переменную в заголовок пакета (чтобы он был общедоступен), а затем выполнить динамический PL / SQL.Вы можете инкапсулировать переменную строки, если ваш динамический блок pl / sql содержит локальную копию перед каждой проверкой.т. е. представьте это как шаблон для немедленного выполнения.
DECLARE
lNew myTab%ROWTYPE;
lOld myTab%ROWTYPE;
lReturn PLS_INTEGER := 0;
BEGIN
lNew := pStatefulPackage.NewRow;
lOld := pStatefulPackage.OldRow;
IF NVL(lNew.<variable>,'~') != NVL(lOld..<variable>,'~') THEN
:lReturn := 1;
END IF;
END;
С этим много хлопот, чтобы обойти тот факт, что вы не можете связывать переменные записи или логические значения в динамическом SQL.
Это также добавляет много накладных расходов для каждого столбца.
Наконец, я обнаружил, что ALL_TAB_COLUMNS слишком медленный, чтобы использовать его для такого рода вещей - вам нужно будет кэшировать метаданные в локальном pl /sql memory.