Tema9-PLSQL Oracle (7)

Embed Size (px)

Citation preview

  • Resumen PL/SQL III Pgina 1

    FEBRERO - 2009

    Resumen PL/SQL III Curso Base de Datos

    CURSO

    BASE DE

    DATOS PL / SQL

  • Resumen PL/SQL III Pgina 2

    Bloques PL/SQL

    Un bloque PL/SQL es la unidad bsica de todo programa. Todos los programas PL/SQL estn compuestos por bloques, los cuales pueden ser secuenciales o anidados.

    Los tipos de bloques son:

    Bloques annimos

    Se construyen generalmente de manera dinmica y slo se ejecutan una vez.

    Bloques con nombre

    Son como los bloques annimos, pero tienen una etiqueta que le da al bloque un

    nombre.

    Subprogramas

    Son procedimientos, funciones y paquetes que son almacenados en base de datos y se

    ejecutan cuando son invocados.

    Disparadores (Triggers)

    Son bloques con nombre que son almacenados en la base de datos. Son ejecutados

    implcitamente cuando cierto evento ocurre.

  • Resumen PL/SQL III Pgina 3

    Procedimientos

    Un procedimiento es un bloque PL/SQL al que se le asigna un nombre. Un procedimiento se crea para que realice una determinada tarea de gestin.

    Los procedimientos son compilados y almacenados en la base de datos. Gracias a ellos se consigue una reutilizacin eficiente del cdigo, ya que se puede invocar al procedimiento las veces que haga falta desde otro cdigo o desde una herramienta de desarrollo como Oracle Developer. Una vez almacenados pueden ser modificados de nuevo.

    Crear procedimientos

    CREATE [OR REPLACE] PROCEDURE

    [ ( [IN | OUT | IN OUT] ,

    .

    [IN | OUT | IN OUT] ) ] IS

    La opcin REPLACE hace que si ya existe un procedimiento con ese nombre, se reemplaza el anterior con el que se crea ahora. Los parmetros son la lista de variables que necesita el procedimiento para realizar su tarea; se indica el tipo de los mismos, pero no su tamao (VARCHAR2 y no VARCHAR2(50)).

    En los parmetros, el modo pueden ser las palabras IN, OUT o IN OUT.

    La palabra DECLARE no se utiliza, la seccin de declaraciones figura tras las palabras IS o AS.

    es un bloque PL/SQL que contiene el cdigo para el procedimiento.

  • Resumen PL/SQL III Pgina 4

    CREATE OR REPLACE PROCEDURE SALUDO IS

    BEGIN

    DBMS_OUTPUT.PUT_LINE('ALMACENES VISIN FUTURA') ;

    END;

    Para ejecutar este procedimiento desde la lnea de comando se usa la instruccin:

    BEGIN SALUDO;

    END;

    CREATE OR REPLACE PROCEDURE VISUALIZAR(TEXTO IN VARCHAR2) IS

    BEGIN

    DBMS_OUTPUT.PUT_LINE(TEXTO) ;

    END;

    /

    BEGIN

    VISUALIZAR('Empresa de Marketin Promocional');

    VISUALIZAR('Logstica propia');

    END;

    /

    Borrar procedimientos

    El comando DROP PROCEDURE elimina el procedimiento indicado.

    DROP PROCEDURE

  • Resumen PL/SQL III Pgina 5

    Funciones

    Las funciones son similares a los procedimientos. La diferencia es que las funciones al menos deben de regresar un valor.

    Crear funciones

    CREATE [OR REPLACE] FUNCTION

    [ ( [IN | OUT | IN OUT] ,

    .

    [IN | OUT | IN OUT] ) ]

    RETURN IS

    Donde es un bloque PL/SQL que contiene el cdigo para la funcin, y

    dentro de ste debe estar la instruccin RETURN. Toda funcin ha de devolver un valor, lo cual

    implica utilizar la instruccin RETURN seguida del valor que se devuelve.

    CREATE OR REPLACE FUNCTION MULTIPLICAR(N1 NUMBER,N2 NUMBER ) RETURN NUMBER IS

    TOT NUMBER;

    BEGIN

    TOT:= N1 * N2;

    RETURN TOT;

    END;

    /

    La llamada a una funcin debe de ser parte de una instruccin SQL. As, una manera de

    ejecutar la funcin MULTIPLICAR podra ser:

    SELECT MULTIPLICAR(3,5) FROM DUAL;

  • Resumen PL/SQL III Pgina 6

    SELECT PRECIO_VENTA_ART "PRECIO 2007", MULTIPLICAR(PRECIO_VENTA_ART ,1.05) "PRECIO 2008"

    FROM TARTICULO;

    DECLARE

    PRECIO_UNITARIO NUMBER :=25 ;

    UNIDADES NUMBER :=8 ;

    BEGIN

    VISUALIZAR(MULTIPLICAR(PRECIO_UNITARIO,UNIDADES)) ;

    END;

    DESC MULTIPLICAR;

    Borrar funciones

    El comando DROP FUNCTION elimina la funcin indicada.

    DROP FUNCTION

  • Resumen PL/SQL III Pgina 7

    MODOS DE LOS PARMETROS

    IN - El valor del parmetro real se pasa al procedimiento cuando se produce la llamada al

    mismo. Dentro del procedimiento, el parmetro formal se comporta como una constante (Solo

    lectura). Cuando el procedimiento finaliza y devuelve el control al entorno en el que se

    produjo la llamada, el parmetro real no se modifica.

    OUT - Se ignora cualquier valor que el parmetro real pueda tener cuando se produzca la

    llamada al procedimiento. Dentro del procedimiento, el parmetro formal se comporta como

    una variable sin inicializar, por lo que contiene el valor NULL. Puede leerse dicha variable y en

    escribirse en ella. Cuando el procedimiento finaliza y devuelve el control al entorno en el que

    se produjo la llamada, se asigna el valor del parmetro formal al parmetro real.

    IN OUT - Este mtodo es una combinacin de los modos IN y OUT. El valor del parmetro real

    se pasa al procedimiento cuando se produce la llamada. Dentro del procedimiento, el

    parmetro formal se comporta como una variable inicializada, pudindose leer y escribir en

    ella. Cuando el procedimiento finaliza y devuelve el control al entorno en el que se produjo la

    llamada, los contenidos del parmetro formal se asignan al parmetro real.

    -- Este procedimiento ilustra diferentes modos de parmetros y asignaciones de parmetros

    CREATE OR REPLACE PROCEDURE TEST (

    p_In IN NUMBER,

    p_Out OUT NUMBER,

    p_InOut IN OUT NUMBER) IS

    v_LocalVariable NUMBER := 0;

    BEGIN

    DBMS_OUTPUT.PUT_LINE('AL PRINCIPIO DE Test:');

    IF (p_In IS NULL) THEN

    DBMS_OUTPUT.PUT('p_In is NULL');

    ELSE

    DBMS_OUTPUT.PUT('p_In = ' || p_In);

    END IF;

    IF (p_Out IS NULL) THEN

    DBMS_OUTPUT.PUT(' p_Out is NULL');

    ELSE

    DBMS_OUTPUT.PUT(' p_Out = ' || p_Out);

    END IF;

    IF (p_InOut IS NULL) THEN

    DBMS_OUTPUT.PUT_LINE(' p_InOut is NULL');

    ELSE

    DBMS_OUTPUT.PUT_LINE(' p_InOut = ' || p_InOut);

    END IF;

  • Resumen PL/SQL III Pgina 8

    /* Asignacin de p_In a v_LocalVariable. Esto est, permitido, ya que se lee de un parmetro con modo IN y no se

    escribe en el mismo. */

    v_LocalVariable := p_In; -- Legal

    /* Asignacin de 7 a p_In. Esto NO EST PERMITIDO, ya que se estara escribiendo en un parmetro con modo IN. */

    -- p_In := 7; -- Ilegal

    /* Asignacin de 7 a p_Out. Esto est permitido, ya que se est escribiendo en un parmetro con modo OUT. */

    p_Out := 7; -- Legal

    /* Asignacin de p_Out a v_LocalVariable. En versiones anteriores a la 7.3, no est permitida la lectura de parmetros con

    modo OUT. */

    v_LocalVariable := p_Out; -- Posiblemente ilegal

    /* Asignacin de p_InOutParameter a v_LocalVariable. Esto est permitido, ya que se lee de un parmetro con modo IN

    OUT. */

    v_LocalVariable := p_InOut; -- Legal

    /* Asignacin de 8 a p_InOutParameter. Esto est permitido, ya que se escribe en un parmetro con modo IN OUT. */

    p_InOut := 8; -- Legal

    DBMS_OUTPUT.PUT_LINE('AL FINAL DE Test:');

    IF (p_In IS NULL) THEN

    DBMS_OUTPUT.PUT('p_In is NULL');

    ELSE

    DBMS_OUTPUT.PUT('p_In = ' || p_In);

    END IF;

    IF (p_Out IS NULL) THEN

    DBMS_OUTPUT.PUT(' p_Out is NULL');

    ELSE

    DBMS_OUTPUT.PUT(' p_Out = ' || p_Out);

    END IF;

    IF (p_InOut IS NULL) THEN

    DBMS_OUTPUT.PUT_LINE(' p_InOut is NULL');

    ELSE

    DBMS_OUTPUT.PUT_LINE(' p_InOut = ' || p_InOut);

    END IF;

    END Test;

    /

    -- Este bloque llama a Test.

    DECLARE

    v_In NUMBER := 1;

    v_Out NUMBER := 2;

    v_InOut NUMBER := 3;

    BEGIN

    DBMS_OUTPUT.PUT_LINE('ANTES DE LLAMAR A TEST:');

    DBMS_OUTPUT.PUT_LINE('v_In = ' || v_In ||' v_Out = ' || v_Out ||' v_InOut = ' || v_InOut);

    Test(v_In, v_Out, v_InOut);

    DBMS_OUTPUT.PUT_LINE('DESPUES DE LLAMAR A TEST:');

    DBMS_OUTPUT.PUT_LINE(' v_In = ' || v_In ||' v_Out = ' || v_Out ||' v_InOut = ' || v_InOut);

    END;

    /

  • Resumen PL/SQL III Pgina 9

    Funcin FACTORIAL

    La siguiente funcin, calcula el valor factorial a partir de un nmero recibido.

    CREATE OR REPLACE FUNCTION FACTORIAL(N IN NUMBER) RETURN NUMBER IS

    BEGIN

    IF N PRECIOMEDIO;

  • Resumen PL/SQL III Pgina 10

    LITERALES Y CONSTANTES COMO PARMETROS REALES

    Debido al funcionamiento de los modos de parmetros, todo parmetro real que se

    corresponda con un parmetro OUT o IN OUT debe ser una variable, y no podr ser una

    constante o una expresin. Debe de existir una ubicacin para almacenar el valor que se

    devuelve.

    CREATE OR REPLACE PROCEDURE TEST1 ( p_Out OUT NUMBER ) IS

    v_LocalVariable NUMBER := 5;

    BEGIN

    p_Out := v_LocalVariable;

    END;

    /

    DECLARE

    var CONSTANT NUMBER(3,2):=0.16;

    BEGIN

    TEST1(var);

    END;

  • Resumen PL/SQL III Pgina 11

    RESTRICCIONES SOBRE LOS PARMETROS FORMALES

    Cuando llamamos a un procedimiento, se pasan los valores de los parmetros reales y dentro

    del procedimiento, hacemos referencia a los mismos utilizando los parmetros formales. Las

    restricciones sobre las variables tambin se pasan como parte del mecanismo de paso de

    parmetros. En la declaracin de un procedimiento no podemos restringir la longitud de los

    parmetros de tipo CHAR o VARCHAR2, ni la precisin y/o escala de los de tipo NUMBER,

    debido a que las restricciones se tomarn de los parmetros reales.

    -- Ejemplo de procedimiento errneo

    CREATE OR REPLACE PROCEDURE Parametros (

    p_Parameter1 IN OUT VARCHAR2(40),

    p_Parameter2 IN OUT NUMBER(3,1)) AS

    BEGIN

    p_Parameter1 := 'abcdefghijklm';

    p_Parameter2 := 12.3;

    END Parametros;

    Por otro lado, se puede generar un error al llamar al procedimiento, si el parmetro real tiene

    una restriccin de longitud menor, que los valores asignados al parmetro formal.

    DECLARE

    v_Parameter1 VARCHAR2(5):= 'abc';

    v_Parameter2 NUMBER(1) :=2;

    BEGIN

    parametros(v_Parameter1 , v_Parameter2 );

    END ;

    ERROR : buffer de cadenas de caracteres demasiado pequeo numrico o de valor

    ERROR : precisin de nmero demasiado grande numrico o de valor

  • Resumen PL/SQL III Pgina 12

    %TYPE Y PARMETROS DE PROCEDIMIENTO

    Aunque no podamos declarar parmetros formales con restricciones, estas pueden imponerse

    utilizando %TYPE. Si declaramos un parmetro formal con %TYPE, y el tipo al que nos

    referimos est restringido, la restriccin actuar sobre el parmetro formal, y no sobre el

    parmetro real.

    CREATE OR REPLACE PROCEDURE Parametros (

    p_Parameter1 IN OUT VARCHAR2,

    p_Parameter2 IN OUT TARTICULO.CODIGO_CAT_ART%TYPE) AS

    BEGIN

    p_Parameter2 := 123;

    END Parametros;

    Segn el ejemplo de PROCEDURE Parametros, p_Parameter2 tiene la restriccin de la columna

    TARTICULO.CODIGO_CAT_ART, que est de finida como NUMBER(3), por lo cual la siguiente

    llamada al procedimiento Parametros generar un error.

    DECLARE

    v_Parameter1 VARCHAR2(5):= 'abc';

    v_Parameter2 NUMBER(5) :=12345;

    BEGIN

    parametros(v_Parameter1 , v_Parameter2 );

    END ;

    ERROR : precisin de nmero demasiado grande numrico o de valor

  • Resumen PL/SQL III Pgina 13

    EXCEPCIONES GENERADAS EN UN SUBPROGRAMA

    Si ocurre un error dentro de un subprograma, se genera una excepcin. Si el procedimiento no

    tiene control de excepcin, o bien, se genera la rutina de tratamiento de excepciones, se pasa

    inmediatamente el control al entorno que efectu la llamada, segn la propagacin de

    excepciones. Sin embargo, los valores de los parmetros formales con modo OUT y modo IN

    OUT no se devuelven a los parmetros reales.

    CREATE OR REPLACE PROCEDURE RaiseError (

    p_Raise IN BOOLEAN, p_ParameterA OUT NUMBER) AS

    BEGIN

    p_ParameterA := 7;

    IF p_Raise THEN

    RAISE DUP_VAL_ON_INDEX;

    END IF;

    END RaiseError;

    DECLARE

    v_TempVar NUMBER := 1;

    BEGIN

    DBMS_OUTPUT.PUT_LINE('Valor inicial: ' || v_TempVar);

    RaiseError(FALSE, v_TempVar);

    DBMS_OUTPUT.PUT_LINE('Valor despus de la 1 llamada: ' || v_TempVar);

    v_TempVar := 2;

    DBMS_OUTPUT.PUT_LINE('Valor antes de la 2 llamada: ' || v_TempVar);

    RaiseError(TRUE, v_TempVar);

    EXCEPTION

    WHEN OTHERS THEN

    DBMS_OUTPUT.PUT_LINE('Valor despus de la 2 llamada: ' || v_TempVar);

    END;

  • Resumen PL/SQL III Pgina 14

    PASO DE PARMETROS POR REFERENCIA Y POR VALOR

    Los parmetros de los subprogramas pueden pasarse por referencia o por valor. Cuando se

    pasa un parmetro por referencia, lo que se pasa al parmetro formal correspondiente es un

    puntero al parmetro real. Cuando se pasa un parmetro por valor, se copia el valor del

    parmetro real al parmetro formal. El paso de parmetro por referencia es generalmente ms

    rpido, ya que ahorra la realizacin de la copia, especialmente en el caso de parmetros de

    colecciones (tablas, varrays). De forma predeterminada, PL/SQL pasa los parmetros de modo

    IN por referencia y los parmetros de modo IN OUT y OUT por valor, para mantener la

    semntica de excepciones y para que las restricciones sobre parmetros reales puedan

    verificarse.

    UTILIZACIN DE NOCOPY

    A partir de Oracle 8i se incluye la indicacin de compilacin NOCOPY, la sintaxis para utilizar

    dicha indicacin a la hora de declarar un parmetro es la siguiente

    NOCOPY

    Si NOCOPY est especificado, el compilador PL/SQL intenta pasar el parmetro por referencia,

    en lugar de por valor.

    CREATE OR REPLACE PROCEDURE NoCopyTest (

    p_InParametro IN NUMBER,

    p_OutParametro OUT NOCOPY VARCHAR2,

    p_InOutParametro IN OUT NOCOPY CHAR) IS

    BEGIN

    NULL;

    END NoCopyTest;

    La utilizacin de NOCOPY con un parmetro de modo IN da error de compilacin.

    Cuando pasamos un parmetro por referencia, cualquier modificacin del parmetro formal

    tambin modifica el parmetro real, ya que ambos apuntan al mismo lugar. Esto significa que,

    si se produce una excepcin despus de haber modificado el parmetro formal, el valor

    original del parmetro real se habr perdido.

  • Resumen PL/SQL III Pgina 15

    CREATE OR REPLACE PROCEDURE RaiseError (

    p_Raise IN BOOLEAN,

    p_ParameterA OUT NOCOPY NUMBER) AS

    BEGIN

    p_ParameterA := 7;

    IF p_Raise THEN

    RAISE DUP_VAL_ON_INDEX;

    ELSE

    RETURN;

    END IF;

    END RaiseError;

    /

    DECLARE

    v_TempVar NUMBER := 1;

    BEGIN

    DBMS_OUTPUT.PUT_LINE('Valor inicial: ' || v_TempVar);

    RaiseError(FALSE, v_TempVar);

    DBMS_OUTPUT.PUT_LINE('Valor despus de la 1 llamada: ' || v_TempVar);

    v_TempVar := 2;

    DBMS_OUTPUT.PUT_LINE('Valor antes de la 2 llamada: ' || v_TempVar);

    RaiseError(TRUE, v_TempVar);

    EXCEPTION

    WHEN OTHERS THEN

    DBMS_OUTPUT.PUT_LINE('Valor despus de la 2 llamada: ' || v_TempVar);

    END;

  • Resumen PL/SQL III Pgina 16

    NOTACIN POSICIONAL Y NOTACIN NOMINAL

    Los parmetros formales se encuentran asociados a los parmetros reales por su posicin.

    Alternativamente puede realizarse una llamada a un procedimiento utilizando la notacin

    nominal, en la cual, para cada argumento, se incluye tanto el parmetro formal, como el

    parmetro real, lo que nos permite modificar el orden de los argumentos.

    Las notaciones nominal y posicional pueden utilizarse conjuntamente en la misma llamada, en

    tal caso, los primeros argumentos a especificar deben ser por posicin.

    CREATE OR REPLACE PROCEDURE nominal(

    p_ParametroA VARCHAR2,

    p_ParametroB NUMBER,

    p_ParametroC BOOLEAN,

    p_ParametroD DATE) AS

    BEGIN

    NULL;

    END nominal;

    DECLARE

    v_Variable1 VARCHAR2(10);

    v_Variable2 NUMBER(7,6);

    v_Variable3 BOOLEAN;

    v_Variable4 DATE;

    BEGIN

    nominal(p_ParametroA => v_Variable1,

    p_ParametroB => v_Variable2,

    p_ParametroC => v_Variable3,

    p_ParametroD => v_Variable4);

    END;

    Las notaciones nominal y posicional pueden utilizarse conjuntamente en la misma llamada, en

    tal caso, los primeros argumentos a especificar deben ser por posicin.

    DECLARE

    v_Variable1 VARCHAR2(10);

    v_Variable2 NUMBER(7,6);

    v_Variable3 BOOLEAN;

    v_Variable4 DATE;

    BEGIN

    nominal(v_Variable1, v_Variable2,

    p_ParametroC => v_Variable3,

    p_ParametroD => v_Variable4);

    END;

  • Resumen PL/SQL III Pgina 17

    VALOR PREDETERMINADO DE LOS PARAMETROS

    Al igual que las declaraciones de las variables, los parmetros formales pueden tener valores

    predeterminados. Si un determinado parmetro tiene un valor por defecto, no es obligatorio

    pasarlo desde la llamada. Si se pasa valor, el valor del parmetro real sustituir al

    predeterminado.

    La sintaxis a utilizar:

    :=

    DEFAULT

    CREATE OR REPLACE PROCEDURE DefaultTest (

    p_ParametroA NUMBER DEFAULT 10,

    p_ParametroB VARCHAR2 DEFAULT 'abcdef',

    p_ParametroC DATE DEFAULT SYSDATE) AS

    BEGIN

    DBMS_OUTPUT.PUT_LINE('A: '|| p_ParametroA ||' B: ' || p_ParametroB ||' C:' ||

    TO_CHAR(p_ParametroC,'DD-MM-YYYY'));

    END DefaultTest;

    BEGIN

    DefaultTest(p_ParametroA => 7, p_ParametroC => '01-FEB-08');

    END;

    BEGIN

    -- Usa el valor predeterminado tanto para p_ParametroB

    -- como para p_ParametroC.

    DefaultTest(20);

    END;

  • Resumen PL/SQL III Pgina 18

    PAQUETES

    Un paquete es una estructura de PL/SQL que permite almacenar juntos varios objetos

    relacionados entre s. Un paquete tiene dos partes separadas: la especificacin y el cuerpo.

    Cada una de ellas se almacena independientemente en el diccionario de datos.

    Un paquete es fundamentalmente una seccin declarativa. Cualquier cdigo que pueda

    incluirse en la parte declarativa de un bloque puede incluirse en un paquete, incluidos

    procedimientos, funciones, cursores y variables.

    Los paquetes no pueden ser llamados o pasados como parmetros.

    La especificacin del paquete incluye informacin acerca del contenido del paquete. Sin

    embargo no contiene cdigo para ninguno de los procedimientos.

    CREATE [ OR REPLACE ] PACKAGE IS -- Especificaciones de procedimientos -- Especificaciones de funciones -- Declaraciones de variables -- Declaraciones de excepciones -- Declaraciones de cursores

    END [];

    El cuerpo del paquete es un objeto independiente de la cabecera del paquete en el diccionario

    de datos. El cuerpo del paquete no puede compilarse hasta que la cabecera del paquete se

    haya compilado correctamente. El cuerpo contiene el cdigo correspondiente a las

    declaraciones formales de los subprogramas que aparecen en la cabecera del paquete.

    CREATE [ OR REPLACE ] PACKAGE BODY IS

    -- Declaraciones de los subprogramas

    END [];

    Cualquier objeto que se declare en la cabecera del paquete, se encuentra dentro de mbito y

    es visible desde fuera del paquete, siempre que el objeto se distinga precedindole con el

    nombre del paquete donde se encuentra definido.

  • Resumen PL/SQL III Pgina 19

    SOBRECARGA DE SUBPROGRAMAS EMPAQUETADOS

    Los procedimientos y funciones dentro de un paquete pueden sobrecargarse, lo que significa

    que puede haber ms de un procedimiento o una funcin con el mismo nombre, pero con

    diferentes parmetros. La sobrecarga est permitida para distinto nmero de parmetros, o

    bien, para distinto tipo de familia de dato. No est permitida para diferentes tipos retornados

    por una funcin, ni para distintos modos de recepcin de los parmetros (IN, OUT, IN OUT).

    INICIALIZACIN DEL PAQUETE

    El paquete se instancia la primera vez que se llama a uno de los subprogramas en l

    empaquetados, lo que significa que el paquete se lee de disco y se lleva a memoria, y se

    ejecuta el cdigo compilado del subprograma al que se llama. En esta situacin se asigna

    memoria para todas las variables definidas en el paquete. Cada sesin tendr su propia copia

    de las variables empaquetadas, asegurando que dos sesiones que ejecuten subprogramas

    contenidos en el mismo paquete utilicen ubicaciones de memoria diferentes.

    En ocasiones, es conveniente ejecutar un cdigo de inicializacin la primera vez que se

    instancia el paquete, lo que puede hacerse aadiendo una seccin de inicializacin en el

    cuerpo del paquete, despus de todos los dems objetos.

    CREATE [ OR REPLACE ] PACKAGE BODY IS

    BEGIN

    -- Cdigo de Inicializacin

    END [];

  • Resumen PL/SQL III Pgina 20

    ESPECIFICACIN DEL PAQUETE OPERAR

    CREATE OR REPLACE PACKAGE OPERAR IS

    FUNCTION SUMAR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER;

    FUNCTION SUMAR(N1 IN VARCHAR2, N2 IN VARCHAR2) RETURN VARCHAR2;

    FUNCTION RESTAR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER;

    FUNCTION DIVIDIR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER;

    FUNCTION MULTIPLICAR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER;

    RESULTADO NUMBER;

    END OPERAR;

    CUERPO DEL PAQUETE OPERAR

    CREATE OR REPLACE PACKAGE BODY OPERAR IS

    FUNCTION SUMAR(N1 IN NUMBER,N2 IN NUMBER) RETURN NUMBER IS

    BEGIN

    RESULTADO:=N1+N2;

    RETURN RESULTADO;

    END SUMAR;

    FUNCTION RESTAR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER IS

    BEGIN

    RETURN N1-N2;

    END RESTAR;

    FUNCTION MULTIPLICAR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER IS

    BEGIN

    RETURN N1*N2;

    END MULTIPLICAR;

    FUNCTION DIVIDIR(N1 IN NUMBER, N2 IN NUMBER) RETURN NUMBER IS

    BEGIN

    RETURN N1/N2;

    END DIVIDIR;

    FUNCTION SUMAR(N1 IN VARCHAR2, N2 IN VARCHAR2) RETURN VARCHAR2 IS

    BEGIN

    RETURN CONCAT(N1,N2);

    END SUMAR;

    END OPERAR;

    EJECUCIN DEL PAQUETE OPERAR

    SELECT OPERAR.DIVIDIR (12, 3) FROM DUAL;

    SELECT OPERAR.SUMAR (12, 3) FROM DUAL;

    SELECT OPERAR.SUMAR ('BUENAS ', 'TARDES') FROM DUAL;

  • Resumen PL/SQL III Pgina 21

    TRIGGER

    TIPOS DE DISPARADORES

    Los disparadores son parecidos a los procedimientos y funciones, en el sentido de que son

    bloques de PL/SQL con secciones declarativa, ejecutable y de tratamiento de excepciones. Los

    disparadores deben almacenarse en la base de datos como objetos independientes y no

    pueden ser locales a un bloque o paquete. Un TRIGGER difiere en gran medida de un

    procedimiento almacenado en la B.D. ya que unos son ejecutados de manera explcita por el

    usuario, una aplicacin o un TRIGGER y los otros son ejecutados de manera implcita por

    Oracle ante la ocurrencia de algn evento. El suceso que lo activa puede ser una operacin

    DML (INSERT, UPDATE o DELETE) sobre una tabla e incluso en algunas ocasiones sobre una

    vista.

    Existen tres tipos de disparadores: DML, de sustitucin y del sistema.

    Los disparadores son ampliamente empleados en la personalizacin de la Administracin de la

    B.D. por ejemplo: un TRIGGER puede restringir las operaciones DML sobre una tabla en

    particular en ciertas horas del da, durante una o varias semanas o incluso meses. Otras

    aplicaciones de los TRIGGERS pueden ser las siguientes: generacin automtica de valores

    derivados de una columna, prevenir transacciones invlidas, proporcionar auditorias

    sofisticadas, generar estadsticas de acceso, publicar informacin de los eventos generados por

    la B.D., las actividades de los usuarios o de las estructuras SQL que se ha ejecutado.

    CREACIN DE DISPARADORES

    CREATE [OR REPLACE] TRIGGER

    BEFORE | AFTER | INSTEAD OF

    DELETE | INSERT | UPDATE [OF ]

    ON

    [ FOR EACH ROW ]

    [ WHEN ]

    { }

    END [] ;

  • Resumen PL/SQL III Pgina 22

    DISPARADORES DML

    Los disparadores DML se activan a partir de instrucciones DML y el tipo de instruccin

    determina el tipo de disparador. Estos pueden definirse para las instrucciones INSERT, DELETE

    y/o UPDATE y podrn dispararse antes o despus de la operacin. Dichos disparadores pueden

    dispararse en operaciones de fila o de instruccin.

    Las combinaciones de estos factores determinan el tipo de disparador (un total de 12). Un

    disparador puede tambin dispararse para ms de un tipo de instruccin DML sobre una tabla.

    El cdigo de disparador se ejecutar junto con la propia instruccin de disparo, como parte de

    la misma transaccin.

    Una tabla puede tener cualquier nmero de disparadores definido sobre la misma, incluyendo

    ms de un disparador DML del mismo tipo. Por ejemplo, pueden definirse dos disparadores

    posteriores a la insercin y de nivel de fila. Todos los disparadores del mismo tipo se activarn

    de forma secuencial.

    Por defecto el disparador se ejecuta por instruccin, si se desea que se ejecute por cada fila

    que afecte la instruccin, tenemos que especificar la clusula FOR EACH ROW.

    Si deseamos que el disparador se lance cuando afecte a una determinada columna, debemos

    indicarlo mediante la sintaxis OF [ , ...]

    Ejemplos:

    CREATE TRIGGER CAMBIO_CATEGORIA

    BEFORE

    DELETE OR INSERT OR UPDATE

    ON TCATEGORIA

    . .

    .. ..

    END CAMBIO_CATEGORIA;

  • Resumen PL/SQL III Pgina 23

    CREATE TRIGGER CHEQUEAR_ART

    BEFORE

    INSERT OR UPDATE OF PRECIO_VENTA_ART, PESO_ART ON TARTICULO

    FOR EACH ROW

    WHEN (:NEW.CODIGO_CAT_ART = '101')

    . .

    .. ..

    END CHEQUEAR_ART;

    CREATE TRIGGER CHEQUEAR_ART

    BEFORE

    INSERT OR UPDATE OF PRECIO_VENTA_ART, PESO_ART ON TARTICULO

    FOR EACH ROW

    WHEN (NEW.CODIGO_CAT_ART = '101')

    PROCEDIMIENTO_ART (:NEW.CODIGO_ART, :NEW.PESO_ART);

    END CHEQUEAR_ART;

  • Resumen PL/SQL III Pgina 24

    ORDEN DE ACTIVACIN DE LOS DISPARADORES

    1 Ejecucin de los disparadores previos de nivel de instruccin.

    2 Para cada fila aceptada por la instruccin:

    2.A Ejecucin de los disparadores previos de nivel de fila.

    2.B Ejecucin de la propia instruccin.

    2.C Ejecucin de los disparadores posteriores de nivel de fila.

    3 Ejecucin de los disparadores posteriores de nivel de instruccin.

    EJEMPLO ORDEN DE ACTIVACIN

    Secuencia

    CREATE SEQUENCE trig_seq START WITH 1 INCREMENT BY 1 NOCACHE;

    Tabla

    CREATE TABLE temp_table

    ( num_col NUMBER(3),

    char_col VARCHAR2(50) ) ;

  • Resumen PL/SQL III Pgina 25

    Paquete

    CREATE OR REPLACE PACKAGE TrigPackage AS

    -- Contador global que se usa en los disparadores

    v_Contador NUMBER;

    END TrigPackage;

    Disparadores

    CREATE OR REPLACE TRIGGER BINSTRUCCION

    BEFORE UPDATE ON TProveedores

    BEGIN

    -- Puesta a cero del contador.

    TrigPackage.v_Contador := 0;

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL,'Before INSTRUCCION: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END BINSTRUCCION;

    /

    CREATE OR REPLACE TRIGGER AINSTRUCCION1

    AFTER UPDATE ON TProveedores

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL,'After INSTRUCCION 1: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END AINSTRUCCION1;

    /

    CREATE OR REPLACE TRIGGER AINSTRUCCION2

    AFTER UPDATE ON TProveedores

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL, 'After INSTRUCCION 2: Contador = ' ||TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END AINSTRUCCION2;

    /

    CREATE OR REPLACE TRIGGER BFILA1

    BEFORE UPDATE ON TProveedores

    FOR EACH ROW

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL, 'Before FILA 1: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END BFILA1;

    /

  • Resumen PL/SQL III Pgina 26

    Disparadores (Cont.)

    CREATE OR REPLACE TRIGGER BFILA2

    BEFORE UPDATE ON TProveedores

    FOR EACH ROW

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL, 'Before FILA 2: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END BFILA2;

    /

    CREATE OR REPLACE TRIGGER BFILA3

    BEFORE UPDATE ON TProveedores

    FOR EACH ROW

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL, 'Before FILA 3: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END BFILA3;

    /

    CREATE OR REPLACE TRIGGER AFILA

    AFTER UPDATE ON TProveedores

    FOR EACH ROW

    BEGIN

    INSERT INTO temp_table (num_col, char_col)

    VALUES (trig_seq.NEXTVAL, 'After FILA: Contador = ' || TrigPackage.v_Contador);

    -- Incremento del contador para el prximo disparador.

    TrigPackage.v_Contador := TrigPackage.v_Contador + 1;

    END AFILA;

    /

  • Resumen PL/SQL III Pgina 27

    Sentencia activadora

    Y resultado

    UPDATE TProveedores SET poblacion_pr = 'LEGANS' WHERE cod_pr IN ('PCC', 'ASU');

    SELECT * FROM temp_table ORDER BY num_col;

  • Resumen PL/SQL III Pgina 28

    EJEMPLO INICIALIZACION DE UN CODIGO

    SECUENCIALMENTE

    Completa el campo CODIGO_CAT de la tabla de categoras con el prximo valor que genere la

    secuencia CODIGO_CAT. Como CODIGO_CAT es una columna la tabla de categoras,

    :new.CODIGO_CAT es una referencia vlida.

    Secuencia

    Tabla

    SELECT * FROM TCATEGORIA ORDER BY CODIGO_CAT ;

    Disparador

    CREATE OR REPLACE TRIGGER COD_CAT_NUEVO

    BEFORE INSERT ON TCATEGORIA

    FOR EACH ROW

    BEGIN

    SELECT CODIGO_CAT.NEXTVAL INTO :NEW.CODIGO_CAT FROM DUAL;

    END COD_CAT_NUEVO;

  • Resumen PL/SQL III Pgina 29

    Sentencia activadora

    INSERT INTO TCATEGORIA (NOMBRE_CAT ) VALUES ('IMPRESORAS');

    Resultado

    SELECT * FROM TCATEGORIA ORDER BY CODIGO_CAT ;

    IDENTIFICADORES DE CORRELACIN EN DISPARADORES DE NIVEL DE FILA

    Un disparador de nivel de fila se activa una vez por cada fila que procese la instruccin de

    disparo. Dentro del disparador, es posible acceder a los datos de la fila que se est

    procesando. Esto es posible mediante dos identificadores de correlacin :new y :old. El

    carcter dos puntos que les precede, indica que son variables de acoplamiento.

    La sintaxis :new.nombre_campo, es vlida nicamente si nombre_campo es un campo de la

    tabla disparo.

    El identificador :old tendr los valores originales antes del borrado, o de la modificacin y NULL

    para el proceso de insercin.

    El identificador :new tendr los valores nuevos de la modificacin, o de la insercin y NULL

    para el proceso de borrado.

  • Resumen PL/SQL III Pgina 30

    CLUSULA REFERENCING

    Si deseamos dar un nombre diferente para los identificadores de correlacin :new y :old,

    podemos utilizar la clusula referencing. Dicha clusula se incluye despus del suceso de

    disparo y antes de la clusula when y for each row .

    REFERENCING [ OLD AS ] [ NEW AS ]

    En el cuerpo del disparador se podr utilizar :nombre_old y :nombre_new en lugar de :old y

    :new. En la clusula referencing los identificadores se escriben sin los dos puntos.

    EJEMPLO INICIALIZACION DE UN CODIGO

    CLUSULA REFERENCING

    Disparador

    CREATE OR REPLACE TRIGGER COD_CAT_NUEVO

    BEFORE INSERT ON TCATEGORIA

    REFERENCING NEW AS CATEGORIA_NUEVA

    FOR EACH ROW

    BEGIN

    SELECT CODIGO_CAT.NEXTVAL INTO :CATEGORIA_NUEVA.CODIGO_CAT FROM DUAL;

    END COD_CAT_NUEVO;

    Sentencia activadora

    INSERT INTO TCATEGORIA (NOMBRE_CAT ) VALUES ('FOTOGRAFA');

    Resultado

    SELECT * FROM TCATEGORIA ORDER BY CODIGO_CAT ;

  • Resumen PL/SQL III Pgina 31

    CLUSULA WHEN

    La clusula WHEN es nicamente valida en los disparadores de nivel de fila. El cuerpo del

    disparador, solo se ejecutar sobre aquellas filas que cumplan la condicin especificada.

    WHEN

    PREDICADOS DE DISPARADORES

    Para un disparador que se pueda activar por diferentes acciones producidas ( INSERT, DELETE,

    UPDATE) , existen tres funciones booleanas que se pueden utilizar para determinar qu

    operacin ha lanzado el disparador.

    INSERTING

    Verdadero si la instruccin de disparo es INSERT, falso en cualquier otro caso.

    UPDATING

    Verdadero si la instruccin de disparo es UPDATE.

    DELETING

    Verdadero si la instruccin de disparo es DELETE.

    BEGIN

    IF INSERTING THEN

    ;

    ELSIF UPDATING THEN

    ;

    ELSE

    ;

    END IF;

  • Resumen PL/SQL III Pgina 32

    DISPARADORES DE SUSTITUCIN

    A diferencia de los disparadores DML, que actan adems de las operaciones INSERT, UPDATE

    y DELETE, los disparadores de sustitucin actan en lugar de la orden DML.

    Los disparadores de sustitucin pueden definirse nicamente sobre vistas, mientras que los

    disparadores DML se definen sobre tablas.

    Existe una clasificacin entre vistas modificables y vistas no modificables. Una vista modificable

    es aquella que permite una instruccin DML. En general, una vista es modificable si no

    contiene uniones (INNER JOIN, campos de ms de una tabla), agregaciones (SUM, COUNT),

    agrupaciones (GROUP BY) ni el operador DISTINCT.

    Sin embargo algunas vistas que trabajan con ms de una tabla, puede ser modificable si la

    operacin DML ejecutada solo afecta a columnas de una sola tabla base.

    Si una vista no es modificable, es posible escribir un disparador de sustitucin que realice las

    operaciones deseadas, permitiendo as la modificacin de la misma. Los disparadores de

    sustitucin, por supuesto, tambin pueden escribirse para vistas modificables.

    La clusula FOR EACH ROW es opcional para los disparadores de sustitucin, ya que todos los

    disparadores de sustitucin son de nivel de fila, independientemente de poner la clusula o

    no.

  • Resumen PL/SQL III Pgina 33

    EJEMPLO DISPARADOR DE SUSTITUCIN

    Al insertar registros sobre una vista, compuesta por columnas de las tablas proveedores y

    pedidos, se ejecutar ste disparador de sustitucin, que se encarga de crear un nuevo

    registro en la tabla proveedores y otro nuevo registro en la tabla pedidos.

    Vista

    CREATE OR REPLACE VIEW PEDIDOS_COMPRA_PROVEEDOR AS

    SELECT cif_PC cif, cod_pr cod, nombre_pr nombre, comercial_pc comercial, persona_pr persona,

    forma_pago_pc fp

    FROM tproveedores INNER JOIN tpedidos_compra ON cif_pr = cif_pc;

    Disparador

    CREATE OR REPLACE TRIGGER insert_pedido_prov instead OF INSERT ON PEDIDOS_COMPRA_PROVEEDOR

    DECLARE v_pr VARCHAR2(15);

    CURSOR c_prov IS

    SELECT cif_pr

    FROM tproveedores

    WHERE cif_pr = :NEW.cif;

    FUNCTION buscar_pr RETURN boolean IS

    v_encontrado boolean := TRUE;

    BEGIN

    OPEN c_prov;

    FETCH c_prov INTO v_pr;

    v_encontrado := c_proV % FOUND;

    CLOSE c_proV;

    RETURN v_encontrado;

    END buscar_pr;

    BEGIN

    IF NOT BUSCAR_PR() THEN

    INSERT

    INTO tproveedores(cif_pr, nombre_pr, cod_pr)

    VALUES(:NEW.cif, :NEW.nombre, :NEW.cod);

    END IF;

    INSERT

    INTO tpedidos_compra(numero_pedido_pc, cif_pc, comercial_pc, forma_pago_pc)

    VALUES('PC-' || TRIM (' ' FROM TO_CHAR (NUMERO_PEDIDO_PC.NEXTVAL , '000000') ),

    :NEW.cif, :NEW.comercial, :NEW.fp);

    END insert_pedido_prov;

  • Resumen PL/SQL III Pgina 34

    Sentencia activadora

    INSERT INTO PEDIDOS_COMPRA_PROVEEDOR (CIF,COD, NOMBRE, PERSONA, COMERCIAL, FP)

    VALUES ('A-33317884', 'PIO', 'PIONNER', 'JOSE MARIA', 'MARCOS SERRANO', '90');

    Resultado

    select NUMERO_PEDIDO_PC, CIF_PC, FECHA_PEDIDO_PC, FECHA_ENTRADA_PC, FORMA_PAGO_PC,

    COMERCIAL_PC, PORTES_PC, OBSERVACIONES_PC from TPEDIDOS_COMPRA;

    select CIF_PR, COD_PR, NOMBRE_PR, DIR_PR, POBLACION_PR, PROVINCIA_PR, PAIS_PR, CP_PR,TLF1_PR,

    FAX_PR, PERSONA_PR from TPROVEEDORES;

  • Resumen PL/SQL III Pgina 35

    TRIGGERS DEL SISTEMA

    Tanto los disparadores DML como los de sustitucin se disparan junto con, o en lugar de los

    sucesos DML, es decir las instrucciones INSERT, UPDATE o DELETE. Los disparadores del

    sistema por el contrario, se disparan a consecuencia de dos tipos de sucesos distintos los DDL,

    o los de base de datos. Los sucesos DDL incluyen las instrucciones CREATE, ALTER o DROP,

    mientras que los sucesos de base de datos incluyen la conexin y desconexin del servidor, el

    inicio y finalizacin de la sesin de usuario y los errores del servidor.

    CREATE [OR REPLACE] TRIGGER

    BEFORE | AFTER

    |

    ON DATABASE | [.]SCHEMA

    [ WHEN ]

    { PL/SQL Bloque }

    . .

    END [ ] ;

    Un disparador del sistema puede definirse en el nivel de base de datos o en el nivel de

    esquema. Un disparador de nivel de base de datos se activar siempre que ocurra el suceso de

    disparo, mientras que un disparador de nivel de esquema se activara nicamente cuando

    ocurra el suceso de disparo en el esquema especificado. Las palabras clave DATABASE y

    SCHEMA determinan el nivel de un disparador del sistema dado. Si el esquema no se especifica

    mediante la palabra clave SCHEMA, el valor predeterminado es el esquema propietario del

    disparador.

  • Resumen PL/SQL III Pgina 36

    SUCESOS

    STARTUP AFTER Se dispara cuando se inicia una instancia.

    SHUTDOWN BEFORE Se dispara cuando se cierra una instancia.

    SERVERERROR AFTER Se dispara cuando se produce un error.

    LOGON AFTER Se dispara despus de que un usuario se haya conectado a la

    base de datos.

    LOGOFF BEFORE Se dispara al inicio de la finalizacin de una sesin de usuario.

    CREATE BEFORE | AFTER Se dispara antes o despus de la creacin de un objeto en la

    base de datos.

    DROP BEFORE | AFTER Se dispara antes o despus de la eliminacin de un objeto en la

    base de datos.

    ALTER BEFORE | AFTER Se dispara antes o despus de la modificacin de un objeto en

    la base de datos.

  • Resumen PL/SQL III Pgina 37

    EJEMPLO DISPARADOR DE SISTEMA

    Creado como SYSTEM

    Tabla

    CREATE TABLE temp_table

    ( num_col NUMBER(3),

    char_col VARCHAR2(50) ) ;

    Disparador.

    CREATE OR REPLACE TRIGGER TRABAJA_APLICACION

    AFTER DROP OR CREATE OR ALTER ON A01.SCHEMA

    BEGIN

    INSERT INTO temp_table VALUES (8, CONCAT('TRABAJA: ' , USER) );

    END TRABAJA_APLICACION;

    Sentencia activadora. Ejecutado como A01

    CREATE SEQUENCE SECUENCIA_EJEMPLO

    START WITH 10000

    INCREMENT BY 1;

    Sentencia activadora. Ejecutado como A01

    DROP SEQUENCE SECUENCIA_EJEMPLO;

    Resultado

    SELECT * FROM TEMP_TABLE;

  • Resumen PL/SQL III Pgina 38

    Disparador.

    CREATE OR REPLACE TRIGGER CONECTA_TODOS

    AFTER LOGON ON DATABASE

    BEGIN

    INSERT INTO temp_table VALUES (2,CONCAT( 'CONECTADOS USUARIO ' , USER) );

    END CONECTA_TODOS;

    Disparador

    CREATE OR REPLACE TRIGGER CONECTA_APLICACION

    AFTER LOGON ON A01.SCHEMA

    BEGIN

    INSERT INTO temp_table VALUES (1, CONCAT('CONECTA USUARIO ' , USER) );

    END CONECTA_APLICACION;

    Resultado

    SELECT NUM_COL,CHAR_COL FROM TEMP_TABLE ORDER BY NUM_COL ;

  • Resumen PL/SQL III Pgina 39

    FUNCIONES DE ATRIBUTOS DE SUCESOS

    Dentro de los disparadores del sistema hay varias funciones de atributos de sucesos

    disponibles. Estas permiten que el cuerpo de un disparador obtenga informacin sobre el

    suceso de disparo.

    Las funciones de atributos de sucesos son funciones PL/SQL independientes que pertenecen a

    SYS. Por omisin, no existen sinnimos definidos para las mismas, por lo que deben ir

    precedidas de SYS para que puedan resolverse.

    Algunas funciones de atributos de sucesos:

    DICTIONARY_OBJ_TYPE

    Devuelve un VARCHAR2(20), aplicable a los sucesos CREATE, DROP, ALTER. Devuelve el tipo de

    objeto de diccionario sobre el que tuvo lugar la operacin DDL que activ el suceso.

    DICTIONARY_OBJ_NAME

    Devuelve un VARCHAR2(30), aplicable a los sucesos CREATE, DROP, ALTER. Devuelve el

    nombre del objeto de diccionario sobre el que tuvo lugar la operacin DDL que activ el

    suceso.

    DICTIONARY_OBJ_OWNER

    Devuelve un VARCHAR2(30), aplicable a los sucesos CREATE, DROP, ALTER. Devuelve el

    propietario del objeto de diccionario sobre el que tuvo lugar la operacin DDL que activ el

    suceso.

    SYSEVENT

    Devuelve un VARCHAR2(20), aplicable a todos los sucesos. Devuelve el suceso del sistema que

    activ el disparador.

    LOGIN_USER

    Devuelve un VARCHAR2(30), aplicable a todos los sucesos. Devuelve el identificador del

    usuario que activ el disparador.

  • Resumen PL/SQL III Pgina 40

    EJEMPLO DISPARADOR DE SISTEMA

    Creado como SYSTEM

    Tabla.

    CREATE TABLE NUEVOS_OBJETOS (

    USUARIO VARCHAR2(30),

    OBJETO VARCHAR2(20),

    NOMBRE VARCHAR2(30),

    PROPIETARIO VARCHAR2(30),

    FECHA DATE);

    Disparador.

    CREATE OR REPLACE TRIGGER T_NUEVOS_OBJETOS

    AFTER CREATE ON DATABASE

    BEGIN

    INSERT INTO NUEVOS_OBJETOS (USUARIO, OBJETO, NOMBRE, PROPIETARIO, FECHA)

    VALUES (USER, SYS.DICTIONARY_OBJ_TYPE , SYS.DICTIONARY_OBJ_NAME,

    SYS.DICTIONARY_OBJ_OWNER , SYSDATE);

    END T_NUEVOS_OBJETOS;

    Sentencia activadora. Ejecutado como A01

    CREATE SEQUENCE SECUENCIA_EJEMPLO

    START WITH 10000

    INCREMENT BY 1;

    DROP SEQUENCE SECUENCIA_EJEMPLO;

    Sentencia activadora. Ejecutado como SYSTEM

    CREATE SEQUENCE SECUENCIA_EJEMPLO

    START WITH 10000

    INCREMENT BY 1;

    DROP SEQUENCE SECUENCIA_EJEMPLO;

    CREATE SEQUENCE EJEMPLO2

    START WITH 10000

    INCREMENT BY 1;

    DROP SEQUENCE EJEMPLO2;

    Resultado

    SELECT * FROM NUEVOS_OBJETOS ;

  • Resumen PL/SQL III Pgina 41

    TABLA MUTANTE

    Una tabla mutante es una tabla que se est modificando debido a una instruccin DML. En el

    caso de un disparador es la tabla a la que se refiere el disparador en la clusula ON.

    Un disparador no puede leer o modificar una tabla mutante ni tampoco leer o modificar una

    columna de clave externa relativa a una restriccin de la tabla a la que se refiere el trigger (s

    se podra utilizar y modificar el resto de columnas). Es decir, no podemos hacer consultas ni

    instrucciones DML sobre una tabla sobre la que ya se ha comenzado a modificar, insertar o

    eliminar datos.

    En realidad slo los triggers de fila no pueden acceder a tablas mutantes.

    Por ello la solucin al problema suele ser combinar triggers de tabla con triggers de fila

    (conociendo el orden de ejecucin de los triggers). Normalmente los triggers de fila almacenan

    los valores que se desean cambiar dentro de una tabla preparada al efecto o dentro de

    variables de paquete (accesibles desde cualquier trigger si se crea dentro de dicho paquete).