Oracle PL/SQL:从触发器转发整行到过程

Tim*_*yer 9 oracle triggers plsql stored-procedures

有一个Oracle(10i)PL/SQL行级触发器,负责三个独立的任务.由于触发器相对混乱,我希望将这三个任务导出到三个存储过程中.我在考虑为程序使用my_table%ROWTYPE参数或集合类型,但我主要关心的是如何填充这些参数.

有没有办法将:NEW触发器的整行轻松放入单个变量?到目前为止,我能找到的唯一方法是将每个字段分别分配给不太令人满意的变量,查看代码维护等.

就像是

SELECT :NEW.* INTO <variable> FROM dual;
Run Code Online (Sandbox Code Playgroud)

会优先考虑.(我没有尝试过,但我认为它不起作用)

Jus*_*ave 8

在绝大多数情况下,将行中的新值分配给%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;
Run Code Online (Sandbox Code Playgroud)

如果您的表恰好基于对象声明,则:NEW将是该类型的对象.所以如果你有一张像这样的桌子

CREATE OR REPLACE TYPE obj_foo 
    AS OBJECT (
      column1 NUMBER,
      column2 NUMBER,
      ...
      columnN NUMBER );

CREATE TABLE foo OF obj_foo;
Run Code Online (Sandbox Code Playgroud)

然后你可以声明接受类型的输入参数的程序,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'
Run Code Online (Sandbox Code Playgroud)


Pet*_*ang 3

那样是不可能的。

也许我对另一个问题的回答可以有所帮助。