Вопрос

Внутри триггера я пытаюсь перебрать все столбцы таблицы и сравнить новые значения со старыми значениями.Вот что у меня есть на данный момент:

CREATE OR REPLACE TRIGGER "JOSH".TEST#UPD BEFORE 
UPDATE ON "JOSH"."TEST_TRIGGER_TABLE" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
declare    
   oldval varchar(2000);   
   newval varchar(2000);   
begin    
   for row in (SELECT column_name from user_tab_columns where table_name='TEST_TRIGGER_TABLE') loop  
     execute immediate 'select :old.'||row.column_name||' from dual'   into oldval;  
     execute immediate 'select :new.'||row.column_name||' from dual'   into newval;  
     --Do something here with the old and new values
   end loop;  
end;

Триггер компилируется, но когда он срабатывает, я получаю:

ОРА-01008:не все переменные связаны

при первом выполнении немедленно, поскольку ожидается значение для :old. :old и :new уже определены как часть триггера, но кажется, что выполнение немедленно не видит эти переменные.

Есть ли способ динамически перебирать значения столбцов в триггере?

Это было полезно?

Решение

Нет, вы не можете динамически ссылаться на значения :old и :new.Как предлагает Шейн, вы можете написать код для генерации кода статического триггера, если это облегчит жизнь.Кроме того, вы можете включить «сделать что-нибудь здесь» в процедуру пакета, чтобы ваш триггер стал:

CREATE OR REPLACE TRIGGER JOSH.TEST#UPD BEFORE 
UPDATE ON JOSH.TEST_TRIGGER_TABLE
begin    
   my_package.do_something_with (:old.col1, :new.col1);
   my_package.do_something_with (:old.col2, :new.col2);
   my_package.do_something_with (:old.col3, :new.col3);
   -- etc.
end;

(Кстати, вы можете отказаться от бессмысленного предложения REFERENCING).

Другие советы

Я не уверен, сможете ли вы сделать то, что пытаетесь сделать.По какой причине вы не хотите явно называть столбцы таблицы внутри кода PL/SQL?Если поля таблицы часто меняются, вы можете создать PL/SQL, который динамически создает триггер PL/SQL для каждой таблицы (с явными именами полей в каждой).Каждый раз, когда таблица меняется, вы можете запускать этот PL/SQL для создания нового триггера.

По сути, вы пытаетесь создать собственную систему для аудита всех изменений в таблице?(Мое предположение относительно того, что вы можете делать со старыми и новыми значениями произвольных столбцов.) Если да, возможно, вам стоит изучить собственные возможности аудита Oracle.

У меня была аналогичная проблема, правда в MSSQL.

Мое решение состояло в том, чтобы написать хранимую процедуру, которая перебирает информацию о таблицах и столбцах (либо через словарные представления, либо через собственный репозиторий) и генерирует необходимые триггеры.Процедуру необходимо запускать только в случае изменения модели данных.

Преимущество состоит в том, что вам не нужно перемещаться по метамодели при каждом обновлении, а лучше заранее генерировать триггеры.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top