Oracle PL/SQL:动态循环触发器列
在触发器内部,我尝试循环表上的所有列并将新值与旧值进行比较。 这是我到目前为止所得到的:
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;
触发器编译,但是当触发器触发时,我得到:
ORA-01008: 并非所有变量都绑定
第一个绑定的所有变量都会立即执行,因为它需要 :old
的值。 :old
和 :new
已定义为触发器的一部分,但看起来立即执行无法看到这些变量。
有没有办法动态迭代触发器中的列值?
Inside of a trigger I'm trying to loop over all columns on a table and compare the new values to the old values. Here is what I have so far:
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;
The trigger compiles, but when the trigger fires, I'm getting:
ORA-01008: not all variables bound
on the first execute immediate because it's expecting a value for :old
. :old
and :new
are already defined as part of the trigger, but it appears that execute immediate can't see those variables.
Is there a way to dynamically iterate over the column values in a trigger?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,您不能动态引用 :old 和 :new 值。 正如 Shane 建议的那样,您可以编写代码来生成静态触发代码,如果这能让生活更轻松的话。 另外,您可以将“在这里做某事”放入包过程中,以便您的触发器变为:(
顺便说一下,您可以放弃无意义的 REFERENCING 子句)。
No, you cannot reference :old and :new values dynamically. As Shane suggests, you can write code to generate the static trigger code, if that makes life easier. Also, you can make "do something here" into a package procedure so that your trigger becomes:
(You can ditch the pointless REFERENCING clause by the way).
我不确定你是否能做你想做的事。 您不想在 PL/SQL 代码中显式命名表列的原因是什么? 如果表字段经常更改,您可以构建 PL/SQL,为每个表动态构建 PL/SQL 触发器(每个表中都有显式字段名称)。 每次表发生更改时,您都可以运行该 PL/SQL 来生成新的触发器。
I'm not sure if you can do what you are trying to do. What is the reason you don't want to explicitly name the table columns inside the PL/SQL code? If the table fields are changing often, you could build PL/SQL that dynamically builds the PL/SQL trigger for each table (with the explicit field names in each). Each time the table changes, you could run that PL/SQL to generate the new trigger.
您本质上是在尝试构建自己的系统来审核对表的所有更改吗? (我对您可能对任意列的旧值和新值执行的操作的最佳猜测。)如果是这样,您可能需要研究 Oracle 自己的审计功能。
Are you essentially trying to build your own system to audit all changes to the table? (My best guess as to what you might be doing with the old and new values of arbitrary columns.) If so, you might want to look into Oracle's own auditing capabilities.
我也遇到过类似的问题,尽管是在 MSSQL 中。
我的解决方案是编写一个存储过程,它迭代表和列信息(通过字典视图或自定义存储库)并生成所需的触发器。 仅当数据模型发生更改时才需要运行该过程。
优点是您不必在每次更新中浏览元模型,而是提前生成触发器。
I had a similar problem, although in MSSQL.
My solution was to write a stored procedure which iterates through tables and columns information (either via dictionary views or a custom repository) and generates the required triggers. The procedure needs to be run only if the data model changes.
The advantage is that you don't have to cursor through the metamodel in each update, but rather generate your triggers in advance.