Oracle PL/SQL:将整行从触发器转发到过程
Posted
技术标签:
【中文标题】Oracle PL/SQL:将整行从触发器转发到过程【英文标题】:Oracle PL/SQL: Forwarding whole row to procedure from a trigger 【发布时间】:2011-09-19 09:21:24 【问题描述】:有一个 Oracle (10i) PL/SQL 行级触发器,它负责三个独立的任务。由于触发器相对混乱,我想将这三个任务导出到三个存储过程中。
我正在考虑使用my_table%ROWTYPE
参数或者可能是过程的集合类型,但我主要关心的是如何填充这些参数。
有没有办法将触发器的整个:NEW
行轻松放入单个变量中?
到目前为止,我能找到的唯一方法是将每个字段分别分配给不太令人满意的变量,查看代码维护等。
类似
SELECT :NEW.* INTO <variable> FROM dual;
将是首选。 (我实际上没有尝试过,但我想它不会起作用)
【问题讨论】:
【参考方案1】:那是不可能的。
也许my answer to another question 可以提供帮助。
【讨论】:
不幸的是,对于这个特定的代码,我需要坚持使用 BEFORE I/U/D FOR EACH ROW 触发器。但是说不可能一次复制整行回答了我猜的问题;-)【参考方案2】:在绝大多数情况下,将行中的新值分配给 %ROWTYPE 变量的唯一方法是显式分配每一列。类似的东西
CREATE OR REPLACE TRIGGER some_trigger_name
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
DECLARE
l_row some_table%rowtype;
BEGIN
l_row.column1 := :NEW.column1;
l_row.column2 := :NEW.column2;
...
l_row.columnN := :NEW.columnN;
procedure1( l_row );
procedure2( l_row );
procedure3( l_row );
END;
如果您的表恰好是基于对象声明的,则 :NEW 将是该类型的对象。所以如果你有一张像
CREATE OR REPLACE TYPE obj_foo
AS OBJECT (
column1 NUMBER,
column2 NUMBER,
...
columnN NUMBER );
CREATE TABLE foo OF obj_foo;
然后您可以声明接受OBJ_FOO
类型输入参数的过程并直接从您的触发器中调用这些参数。
不幸的是,另一个线程中关于在 AFTER INSERT/UPDATE 线程中从表中选择行的建议通常不起作用。这通常会导致变异表异常。
1 create table foo (
2 col1 number,
3 col2 number
4* )
SQL> /
Table created.
SQL> create procedure foo_proc( p_foo in foo%rowtype )
2 as
3 begin
4 dbms_output.put_line( 'In foo_proc' );
5 end;
6 /
Procedure created.
SQL> create or replace trigger trg_foo
2 after insert or update on foo
3 for each row
4 declare
5 l_row foo%rowtype;
6 begin
7 select *
8 into l_row
9 from foo
10 where col1 = :new.col1;
11 foo_proc( l_row );
12 end;
13 /
Trigger created.
SQL> insert into foo values( 1, 2 );
insert into foo values( 1, 2 )
*
ERROR at line 1:
ORA-04091: table SCOTT.FOO is mutating, trigger/function may not see it
ORA-06512: at "SCOTT.TRG_FOO", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_FOO'
【讨论】:
【参考方案3】:这类似于贾斯汀的解决方案,但更短一些(每个作业的左侧部分没有打字):
-- use instead of the assignments in Justins example:
select :new.column1,
:new.column2,
...
:new.columnN,
into l_row from dual;
【讨论】:
我突然想到我的解决方案取决于表中列的顺序。【参考方案4】:使用SQL生成SQL;
select ' row_field.'||COLUMN_NAME||' := :new.'||COLUMN_NAME||';' from
ALL_TAB_COLUMNS cols
where
cols.TABLE_NAME = 'yourTableName'
order by cols.column_name
然后复制并粘贴输出。
【讨论】:
以上是关于Oracle PL/SQL:将整行从触发器转发到过程的主要内容,如果未能解决你的问题,请参考以下文章
Oracle pl sql 10g - 将一组行从表移动到具有相同结构的历史表
Oracle笔记4-pl/sql-分支/循环/游标/异常/存储/调用/触发器
使用 PL\SQL Developer 7.0.2 调试 Oracle 触发器?
Oracle 12 PL/SQL 在触发器中检索存储过程名称