2011-06-21 15 views
8

Tiene un desencadenador de nivel de fila PL/SQL de Oracle (10i) que es responsable de tres tareas independientes. Como el desencadenador está relativamente desordenado de esa manera, quiero exportar estas tres tareas en tres procedimientos almacenados. Estaba pensando en usar un parámetro my_table%ROWTYPE o tal vez un tipo de colección para los procedimientos, pero mi principal preocupación es cómo llenar estos parámetros.Oracle PL/SQL: reenvío de toda la fila al procedimiento desde un desencadenador

¿Hay alguna manera de poner toda la fila :NEW de un disparador en una sola variable fácilmente? Hasta ahora la única manera de que pudiera averiguar estaba asignando cada campo por separado a la variable que no es del todo satisfactoria, mirando el mantenimiento del código, etc.

Algo así como

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

sería preferible. (No lo he intentado realmente pero supongo que no funcionaría)

Respuesta

3

No es posible de esa manera.

Tal vez my answer to another question puede ayudar.

+0

Lamentablemente, tengo que mantener el disparador ANTES DE I/U/D PARA CADA FILA para este código específico. Pero al afirmar que no es posible copiar toda la fila de una vez, respondió mi pregunta; supongo ;-) –

8

En la gran mayoría de los casos, la única forma de asignar los nuevos valores en la fila a una variable% ROWTYPE sería asignar explícitamente cada columna. Algo así como

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; 

Si la tabla pasa a ser declarado sobre la base de un objeto,: NUEVO será un objeto de ese tipo. Así que si usted tiene una tabla como

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

CREATE TABLE foo OF obj_foo; 

entonces se podría declarar procedimientos que aceptan parámetros de entrada de tipo OBJ_FOO y llamar a las personas directamente desde su activación.

La sugerencia en el otro hilo acerca de seleccionar la fila de la tabla en un subproceso DESPUÉS DE INSERTAR/ACTUALIZAR, desafortunadamente, generalmente no funciona. Eso generalmente conducirá a una excepción de tabla mutante.

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' 
0

Esto es similar a la solución Justins pero un poco más corta (sin tipificación de parte izquierda de cada asignación):

-- use instead of the assignments in Justins example: 
select :new.column1, 
     :new.column2, 
... 
     :new.columnN, 
into l_row from dual; 
+1

Se me acaba de ocurrir que mi solución depende del orden de las columnas en la tabla. –

2

Uso SQL para generar el SQL;

select ' row_field.'||COLUMN_NAME||' := :new.'||COLUMN_NAME||';' from 
    ALL_TAB_COLUMNS cols 
where 
    cols.TABLE_NAME = 'yourTableName' 
order by cols.column_name 

A continuación, copie y pegue la salida.

Cuestiones relacionadas