Oracle PL/SQL:动态循环触发器列

发布于 2024-07-18 03:32:08 字数 880 浏览 4 评论 0原文

在触发器内部,我尝试循环表上的所有列并将新值与旧值进行比较。 这是我到目前为止所得到的:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一个人的旅程 2024-07-25 03:32:08

不,您不能动态引用 :old 和 :new 值。 正如 Shane 建议的那样,您可以编写代码来生成静态触发代码,如果这能让生活更轻松的话。 另外,您可以将“在这里做某事”放入包过程中,以便您的触发器变为:(

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 子句)。

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:

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;

(You can ditch the pointless REFERENCING clause by the way).

夜还是长夜 2024-07-25 03:32:08

我不确定你是否能做你想做的事。 您不想在 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.

冷夜 2024-07-25 03:32:08

您本质上是在尝试构建自己的系统来审核对表的所有更改吗? (我对您可能对任意列的旧值和新值执行的操作的最佳猜测。)如果是这样,您可能需要研究 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.

她说她爱他 2024-07-25 03:32:08

我也遇到过类似的问题,尽管是在 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文