2011-05-05 5 views
13

En Oracle, se puede escribir un trigger a nivel de fila especificando la cláusula FOR EACH ROW en la declaración CREATE TRIGGER:Al implementar un desencadenante de nivel de extracto en una tabla, ¿es posible obtener los registros VIEJO y NUEVO para todas las filas afectadas?

CREATE TRIGGER MY_FANCY_TRIGGER 
    BEFORE UPDATE ON MY_TABLE 
    FOR EACH ROW 
BEGIN 
    IF :OLD.my_id_column > 4 AND :NEW.some_other_column <> 'foo' THEN 
    -- ... 
    END IF; 
END; 

Tal gatillo le permite ver la antes y después versiones de cada fila afectada (:OLD y :NEW respectivamente). Por ejemplo, la siguiente instrucción hará que este disparador para ejecutar una vez para cada fila de MY_TABLE:

UPDATE MY_TABLE SET some_other_column = 'bar'; 

Mediante la eliminación de la cláusula FOR EACH ROW, el gatillo se convierte en un comunicado gatillo -level. Esto significa que solo se ejecutará una vez por declaración, independientemente de cuántas filas (si las hay) se vieron afectadas por la declaración. Lamentablemente, los desencadenadores de nivel de extracto no tienen las variables :OLD y :NEW disponibles (porque el número de filas afectadas varía).

¿Es posible obtener los :OLD y :NEW valores para todos los filas afectadas dentro de un trigger a nivel de estado de cuenta? Tengo un procesamiento que preferiría que ocurriera una vez por declaración.

Respuesta

10

Un enfoque es el sugerido por Justin Cave para almacenar información en desencadenantes de nivel de fila en colecciones de paquetes independientes.

Si está utilizando 11g, entonces el enfoque correcto será usar activadores compuestos. Esto evita la creación de un paquete separado para guardar la colección de claves, se puede hacer en el propio disparador,

+0

¡Guau, los disparadores compuestos se ven maravillosos! –

+0

Excelente punto. Descuidé eso. –

+0

Estoy aceptando esta respuesta como la solución preferida para avanzar. –

8

No directamente, no.

El enfoque estándar es la "solución de tres gatillo" (más comúnmente utilizado cuando se está tratando de solucionar un problema de tabla mutante)

  1. crear un paquete que contiene una colección de llaves a su mesa
  2. Crear un desencadenante de declaración anterior que inicialice la colección
  3. Cree un desencadenante de nivel de fila que inserte las claves en la colección.
  4. Crear un disparador después de la declaración que utiliza las claves de la colección de hacer su procesamiento

Obviamente, en su caso, esto probablemente sólo añade complejidad al proceso si su trigger a nivel de fila no está causando una mutando el error de la mesa

Como señala josephj1989 a continuación, si está usando 11g, puede usar compound triggers para simplificar esto un poco. Igual declarará una colección, rellenará la colección en un cuerpo de desencadenador a nivel de fila y procesará la colección en el desencadenador de nivel de instrucción. Pero solo habrá un objeto para crear y administrar en lugar de múltiples objetos.

+0

Enfoque interesante. Tienes razón, agrega complejidad, pero puede ser mi única opción (10g). ¿La declaración * * desencadena el nivel de disparo antes * de la fila *? Disparadores de nivel? –

+0

Un desencadenante de instrucción anterior se desencadena antes de un desencadenante de inserción antes de insertar/actualizar/eliminar a nivel de fila. Un desencadenante de instrucción posterior se activa después de un desencadenante de inserción/actualización/eliminación a nivel de fila. –

Cuestiones relacionadas