Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle PL/SQL: Forwarding whole row to procedure from a trigger

In have an Oracle (10i) PL/SQL Row-Level trigger which is responsible for three independent tasks. As the trigger is relatively cluttered that way, I want to export these three tasks into three stored procedures. I was thinking of using a my_table%ROWTYPE parameter or maybe a collection type for the procedures, but my main concern is how to fill these parameters.

Is there a way to put the whole :NEW row of a trigger into a single variable easily? So far the only way I could find out was assigning each field separately to the variable which is not quite satisfying, looking at code maintenance etc.

Something like

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

would be preferred. (I haven't tried that actually but I suppose it wouldn't work)

like image 350
Tim Meyer Avatar asked Jun 21 '11 09:06

Tim Meyer


2 Answers

In the vast majority of cases, the only way to assign the new values in the row to a %ROWTYPE variable would be to explicitly assign each column. Something like

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;

If your table happens to be declared based on an object, :NEW will be an object of that type. So if you have a table like

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

CREATE TABLE foo OF obj_foo;

then you could declare procedures that accept input parameters of type OBJ_FOO and call those directly from your trigger.

The suggestion in the other thread about selecting the row from the table in an AFTER INSERT/ UPDATE thread, unfortunately, does not generally work. That will generally lead to a mutating table exception.

  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'
like image 172
Justin Cave Avatar answered Oct 21 '22 20:10

Justin Cave


It's not possible that way.

Maybe my answer to another question can help.

like image 24
Peter Lang Avatar answered Oct 21 '22 21:10

Peter Lang