【问题标题】:Oracle PL/SQL: Forwarding whole row to procedure from a triggerOracle PL/SQL:将整行从触发器转发到过程
【发布时间】:2011-09-19 09:21:24
【问题描述】:

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

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

类似

SELECT :NEW.* INTO <variable> FROM dual;

将是首选。 (我实际上没有尝试过,但我想它不会起作用)

【问题讨论】:

    标签: oracle stored-procedures plsql triggers


    【解决方案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
      

      然后复制并粘贴输出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-10
        • 1970-01-01
        • 2020-07-15
        相关资源
        最近更新 更多