Está en la página 1de 21

Disparador (old y new)

Problema:

Una librería almacena los datos de sus libros en una tabla denominada "libros" y controla las
actualizaciones del precio de los libros almacenando en la tabla "control" el nombre del usuario, la
fecha, el precio anterior y el nuevo.

Eliminamos las tablas:

drop table control;

drop table libros;

Creamos las tablas con las siguientes estructuras:

create table libros(

codigo number(6),

titulo varchar2(40),

autor varchar2(30),

editorial varchar2(20),

precio number(6,2)

);

create table control(

usuario varchar2(30),

fecha date,

codigo number(6),

precioanterior number(6,2),

precionuevo number(6,2) );

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);

insert into libros values(103,'El aleph','Borges','Emece',28);

insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);

insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);

insert into libros values(145,'Alicia en el pais de las maravillas','Carroll','Planeta',35);


Creamos un trigger a nivel de fila que se dispara "antes" que se ejecute un "update" sobre el
campo "precio" de la tabla "libros". En el cuerpo del disparador se debe ingresar en la tabla
"control", el nombre del usuario que realizó la actualización, la fecha, el código del libro que ha
sido modificado, el precio anterior y el nuevo:

create or replace trigger tr_actualizar_precio_libros

before update of precio

on libros

for each row

begin

insert into control values(user,sysdate,:new.codigo,:old.precio,:new.precio);

end tr_actualizar_precio_libros;

Cuando el trigger se dispare, antes de ingresar los valores a la tabla, almacenará en "control",
además del nombre del usuario y la fecha, el precio anterior del libro y el nuevo valor.

Actualizamos el precio del libro con código 100:

update libros set precio=30 where codigo=100;

Veamos lo que se almacenó en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente.

Actualizamos varios registros:

update libros set precio=precio+precio*0.1 where editorial='Planeta';

Veamos lo que se almacenó en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente de cada registro afectado por la actualización.

Modificamos la editorial de un libro:

update libros set editorial='Sudamericana' where editorial='Planeta';

El trigger no se disparó, pues fue definido para actualizaciones del campo "precio" unicamente.
Verifiquémoslo:

select *from control;

Vamos a reemplazar el trigger anteriormente creado. Ahora el disparador


"tr_actualizar_precio_libros" debe controlar el precio que se está actualizando, si supera los 50
pesos, se debe redondear tal valor a entero hacia abajo (empleando "floor"), es decir, se modifica
el valor ingresado accediendo a ":new.precio" asignándole otro valor:

create or replace trigger tr_actualizar_precio_libros

before update of precio

on libros

for each row

begin

if (:new.precio>50) then

:new.precio:=floor(:new.precio);

end if;

insert into control values(user,sysdate,:new.codigo,:old.precio,:new.precio);

end tr_actualizar_precio_libros;

Vaciamos la tabla "control":

truncate table control;

Actualizamos el precio del libro con código 100:

update libros set precio=54.99 where codigo=100;

Veamos cómo se actualizó tal libro en "libros":

select *from libros where codigo=100;

El nuevo precio actualizado se redondeó a 54.

Veamos lo que se almacenó en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente.

Truncamos la tabla "control" nuevamente:

truncate table control;


Creamos un disparador para múltiples eventos, que se dispare al ejecutar "insert", "update" y
"delete" sobre "libros". En el cuerpo del trigger se realiza la siguiente acción: se almacena el
nombre del usuario, la fecha y los antiguos y viejos valores de "precio":

create or replace trigger tr_libros

before insert or update or delete

on libros

for each row

begin

insert into control values(user,sysdate,:old.codigo,:old.precio,:new.precio);

end tr_libros;

Ingresamos un registro:

insert into libros values (150,'El gato con botas','Anonimo','Emece',21);

Veamos lo que se almacenó en "control":

select *from control;

Resultado:
USUARIO FECHA CODIGO PRECIOANTERIOR PRECIONUEVO

-----------------------------------------------------------------------------------

SYSTEM 20/03/08 21

La sentencia disparadora fue una inserción, por lo tanto, los campos ":old.codigo" y ":old.precio"
contienen "null", así que en "codigo" y en "precioanterior" se almacena "null"; el único campo con
valor diferente de "null" es "precionuevo" correspondiente al valor de ":new.precio".

Actualizamos el campo "precio" de un libro:

update libros set precio=12 where codigo=103;

Veamos lo que se almacenó en "control":

select *from control;

Resultado:
USUARIO FECHA CODIGO PRECIOANTERIOR PRECIONUEVO

-----------------------------------------------------------------------------------

SYSTEM 20/03/08 103 28 12

Analicemos: actualizamos el precio, por lo tanto, ninguno de los campos consultados contiene
"null".
Actualizamos un campo diferente de "precio" de un libro:

update libros set autor='J.L.Borges' where autor='Borges';

Veamos lo que se almacenó en "control":

select *from control;

Resultado:
USUARIO FECHA CODIGO PRECIOANTERIOR PRECIONUEVO

-----------------------------------------------------------------------------------

SYSTEM 20/03/08 103 12 12

Actualizamos el autor, por lo tanto, los campos ":old.precio" y ":new.precio" son iguales.

Eliminamos un registro de "libros":

delete from libros where codigo=100;

Veamos lo que se almacenó en "control":

select *from control;

Resultado:
USUARIO FECHA CODIGO PRECIOANTERIOR PRECIONUEVO

-----------------------------------------------------------------------------------

SYSTEM 20/03/08 100 54

Analicemos: la sentencia que disparó el trigger fue un "delete", por lo tanto, el campo
":new.precio" contiene "null".

Veamos qué informa el diccionario "user_triggers" respecto del trigger anteriormente creado:

select *from user_triggers where trigger_name ='TR_LIBROS';


Disparadores (habilitar y deshabilitar)

Problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados". En
una tabla denominada "controlCambios" guarda los cambios que se realizan en la tabla
"empleados", en ella almacena el nombre del usuario que realiza la modificación, la fecha, el valor
anterior del campo modificado y el nuevo valor.

Eliminamos las tablas:

drop table empleados;

drop table controlCambios;

Creamos las tablas, con las siguientes estructuras:

create table empleados(

documento char(8) not null,

nombre varchar2(30) not null,

domicilio varchar2(30),

seccion varchar2(20)

);

create table controlCambios(

usuario varchar2(30),

fecha date,

datoanterior varchar2(30),

datonuevo varchar2(30)

);

Ingresamos algunos registros:

insert into empleados values('22222222','Ana Acosta','Bulnes 56','Secretaria');


insert into empleados values('23333333','Bernardo Bustos','Bulnes 188','Contaduria');

insert into empleados values('24444444','Carlos Caseres','Caseros 364','Sistemas');

insert into empleados values('25555555','Diana Duarte','Colon 1234','Sistemas');

insert into empleados values('26666666','Diana Duarte','Colon 897','Sistemas');

insert into empleados values('27777777','Matilda Morales','Colon 542','Gerencia');

Creamos un disparador que se active cuando modificamos algún campo de "empleados" y


almacene en "controlCambios" el nombre del usuario que realiza la actualización, la fecha, el dato
que se cambia y el nuevo valor:

create or replace trigger tr_actualizar_empleados

before update

on empleados

for each row

begin

if updating('documento') then

insert into controlCambios values(user,sysdate, :old.documento, :new.documento);

end if;

if updating('nombre') then

insert into controlCambios values(user,sysdate, :old.nombre, :new.nombre);

end if;

if updating('domicilio') then

insert into controlCambios values(user,sysdate, :old.domicilio, :new.domicilio);

end if;

if updating('seccion') then

insert into controlCambios values(user,sysdate, :old.seccion, :new.seccion);

end if;

end tr_actualizar_empleados;

Creamos otro desencadenador que se active cuando ingresamos un nuevo registro en


"empleados", debe almacenar en "controlCambios" el nombre del usuario que realiza el ingreso, la
fecha, "null" en "datoanterior" (porque se dispara con una inserción) y en "datonuevo" el
documento:

create or replace trigger tr_ingresar_empleados

before insert

on empleados

for each row

begin

insert into controlCambios values(user,sysdate, null, :new.documento);

end tr_ingresar_empleados;

Creamos un tercer trigger sobre "empleados" que se active cuando eliminamos un registro en
"empleados", debe almacenar en "controlCambios" el nombre del usuario que realiza la
eliminación, la fecha, el documento en "datoanterior" y "null" en "datonuevo":

create or replace trigger tr_eliminar_empleados

before delete

on empleados

for each row

begin

insert into controlCambios values(user,sysdate, :old.documento, null);

end tr_eliminar_empleados;

Los tres triggers están habilitados. Consultamos el diccionario "user_triggers" para corroborarlo:

select trigger_name, triggering_event, status

from user_triggers

where trigger_name like 'TR%EMPLEADOS';

Vamos a ingresar un empleado y comprobar que el trigger "tr_ingresar_empleados" se dispara


recuperando los registros de "controlCambios":
insert into empleados values('28888888','Pedro Perez','Peru 374','Secretaria');

select *from controlCambios;

Deshabilitamos el trigger "tr_ingresar_empleados":

alter trigger tr_ingresar_empleados disable;

Consultamos el diccionario "user_triggers" para corroborarlo:

select trigger_name, status

from user_triggers

where trigger_name like 'TR%EMPLEADOS';

El trigger "tr_ingresar_empleados" está deshabilitado, "tr_actualizar_empleados" y


"tr_elimnar_empleados" están habilitados.

Vamos a ingresar un empleado y comprobar que el trigger de inserción no se dispara recuperando


los registros de "controlCambios":

insert into empleados values('29999999','Rosa Rodriguez','Rivadavia 627','Secretaria');

select *from controlCambios;

Vamos a actualizar el domicilio de un empleado y comprobar que el trigger de actualización se


dispara recuperando los registros de "controlCambios":

update empleados set domicilio='Bulnes 567' where documento='22222222';

select *from controlCambios;

Deshabilitamos el trigger "tr_actualizar_empleados":

alter trigger tr_actualizar_empleados disable;

Consultamos el diccionario "user_triggers" para corroborarlo:


select trigger_name, status

from user_triggers

where trigger_name like 'TR%EMPLEADOS';

Los triggers "tr_ingresar_empleados" y "tr_actualizar_empleados" están deshabilitados,


"tr_eliminar_empleados" está habilitado.

Vamos a borrar un empleado de "empleados" y comprobar que el trigger de borrado se disparó


recuperando los registros de "controlCambios":

delete from empleados where documento= '29999999';

select *from controlCambios;

Deshabilitamos el trigger "tr_eliminar_empleados":

alter trigger tr_eliminar_empleados disable;

Consultamos el diccionario "user_triggers" para comprobarlo:

select trigger_name, status

from user_triggers

where table_name = 'EMPLEADOS';

Los tres trigger establecidos sobre "empleados" están deshabilitados.

Eliminamos un empleado de "empleados" y comprobamos que el trigger de borrado no se dispara


recuperando los registros de "controlCambios":

delete from empleados where documento= '28888888';

select *from controlCambios;

Habilitamos el trigger "tr_actualizar_empleados":

alter trigger tr_actualizar_empleados enable;


Actualizamos la sección de un empleado y comprobamos que el trigger de actualización se dispara
recuperando los registros de "controlCambios":

update empleados set seccion='Sistemas' where documento='23333333';

select *from controlCambios;

Habilitamos todos los triggers establecidos sobre "empleados":

alter table empleados enable all triggers;

Consultamos el diccionario "user_triggers" para comprobar que el estado (status) de todos los
triggers establecidos sobre "empleados" es habilitado:

select trigger_name, triggering_event, status

from user_triggers

where table_name = 'EMPLEADOS';

Los tres trigger establecidos sobre "empleados" han sido habilitados. Se activarán ante cualquier
sentencia "insert", "update" y "delete".
Disparador (eliminar)

Problema:

Una librería almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario, la fecha, y el tipo de modificación que se realizó sobre la tabla "libros".

Eliminamos la tabla "libros" y la tabla "control":

drop table libros;

drop table control;

Creamos las tablas con las siguientes estructuras:

create table libros(

codigo number(6),

titulo varchar2(40),

autor varchar2(30),

editorial varchar2(20),

precio number(6,2)

);

create table control(

usuario varchar2(30),

fecha date,

operacion varchar2(20)

);

Creamos un desencadenador que se active cuando ingresamos un nuevo registro en "libros", debe
almacenar en "control" el nombre del usuario que realiza el ingreso, la fecha e "insercion" en
"operacion":
create or replace trigger tr_ingresar_libros

before insert

on libros

for each row

begin

insert into control values(user,sysdate,'insercion');

end tr_ingresar_libros;

Creamos un segundo disparador que se active cuando modificamos algún campo de "libros" y
almacene en "control" el nombre del usuario que realiza la actualización, la fecha y en "operacion"
coloque el nombre del campo actualizado:

create or replace trigger tr_actualizar_libros

before update

on libros

for each row

begin

if updating('codigo') then

insert into control values(user,sysdate,'codigo');

end if;

if updating('titulo') then

insert into control values(user,sysdate,'titulo');

end if;

if updating('autor') then

insert into control values(user,sysdate,'autor');

end if;

if updating('editorial') then

insert into control values(user,sysdate,'editorial');

end if;

if updating('precio') then
insert into control values(user,sysdate,'precio');

end if;

end tr_actualizar_libros;

Creamos un tercer trigger sobre "libros" que se active cuando eliminamos un registro de "libros",
debe almacenar en "control" el nombre del usuario que realiza la eliminación, la fecha y "borrado"
en "operacion":

create or replace trigger tr_eliminar_libros

before delete

on libros

for each row

begin

insert into control values(user,sysdate,'borrado');

end tr_eliminar_libros;

Vemos cuántos triggers están asociados a "libros"; consultamos el diccionario "user_triggers":

select trigger_name, triggering_event, status

from user_triggers

where table_name = 'LIBROS';

Hay tres.

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);

insert into libros values(101,'El aleph','Borges','Emece',28);

insert into libros values(102,'Matematica estas ahi','Paenza','Nuevo siglo',12);

insert into libros values(103,'Aprenda PHP','Molina Mario','Nuevo siglo',55);

insert into libros values(144,'Alicia en el pais de las maravillas','Carroll','Planeta',35);


Comprobamos que el trigge "tr_ingresar_libros" se disparó recuperando los registros de "control":

select *from control;

Hay 5 registros.

Actualizamos la editorial de varios libros y comprobamos que el trigger de actualización se disparó


recuperando los registros de "control":

update libros set editorial='Sudamericana' where editorial='Planeta';

select *from control;

2 nuevos registros.

Borramos un libro de "libros" y comprobamos que el trigger de borrado se disparó recuperando


los registros de "control":

delete from libros where codigo=101;

select *from control;

Actualizamos el autor de un libro y comprobamos que el trigger de actualización se dispara


recuperando los registros de "control":

update libros set autor='Adrian Paenza' where autor='Paenza';

select *from control;

Eliminamos la tabla "libros":

drop table libros;

Consultamos el diccionario "user_triggers" para comprobar que al eliminar "libros" se eliminaron


también los triggers asociados a ella:

select trigger_name, triggering_event, status

from user_triggers
where table_name = 'LIBROS';

Los tres trigger asociados a "libros" han sido eliminados.


Control de flujo (for)

Problema:

En el siguiente ejemplo se muestra la tabla del 3. La variable "f" comienza en cero (límite inferior
del for) y se va incrementando de a uno; el ciclo se repite hasta que "f" llega a 5 (límite superior
del for), cuando llega a 6, el bucle finaliza.

set serveroutput on;

execute dbms_output.enable(20000);

begin

for f in 0..5 loop

dbms_output.put_line('3x'||to_char(f)||'='||to_char(f*3));

end loop;

end;

Para que el contador "f" se decremente en cada repetición, colocamos "reverse"; el contador
comenzará por el valor del límite superior (5) y finalizará al llegar al límite inferior (0)
decrementando de a uno. En este ejemplo mostramos la tabla del 3 desde el 5 hasta el 0:

begin

for f in reverse 0..5 loop

dbms_output.put_line('3*'||to_char(f)||'='||to_char(f*3));

end loop;

end;

Se pueden colocar "for" dentro de otro "for". Por ejemplo, con las siguientes líneas imprimimos las
tablas del 2 y del 3 del 1 al 9:

begin

for f in 2..3 loop

dbms_output.put_line('tabla del '||to_char(f));

for g in 1..9 loop


dbms_output.put_line(to_char(f)||'x'||to_char(g)||'='||to_char(f*g));

end loop;--fin del for g

end loop;--fin del for f

end;

Ingresemos el siguiente lote de comandos en el Oracle SQL Developer:

set serveroutput on;

execute dbms_output.enable(20000);

begin

for f in 0..5 loop

dbms_output.put_line('3x'||to_char(f)||'='||to_char(f*3));

end loop;

end;

begin

for f in reverse 0..5 loop

dbms_output.put_line('3*'||to_char(f)||'='||to_char(f*3));

end loop;

end;

begin

for f in 2..3 loop

dbms_output.put_line('tabla del '||to_char(f));

for g in 1..9 loop

dbms_output.put_line(to_char(f)||'x'||to_char(g)||'='||to_char(f*g));

end loop;--fin del for g

end loop;--fin del for f


end;

/
Control de flujo (while loop)

Problema:

Mostramos la tabla del 3 hasta el 5. En primer lugar activamos el paquete "dbms_output"


para poder emplear los procedimientos de dicho paquete, luego ejecutamos el
procedimiento "dbms_output.enable" para habilitar las llamadas a los procedimientos y
funciones de tal paquete, así podremos emplear la función de salida
"dbms_output.put_line".

set serveroutput on;

execute dbms_output.enable (1000000);

Luego, declaramos la variable numérica "numero" y le asignamos el valor cero; tal variable
contendrá el multiplicando. También declaramos la variable "resultado" de tipo numérico
que almacenará el resultado de cada multiplicación. Comenzamos el bloque "begin... end"
con la estructura repetitiva "while... loop". La condición chequea si el valor de la variable
"numero" es menmor o igual a 5; las sentencias que se repetirán serán:

- multiplicar "numero" por 3 y asignárselo a "resultado",

- imprimir "resultado" y

- incrementar la variable "numero" para que la siguiente vez que se entre al bucle
repetitivo se multiplique 3 por otro número.

declare

numero number:=0;

resultado number;

begin

while numero<=5 loop

resultado:=3*numero;

dbms_output.put_line('3*'||to_char(numero)||'='||to_char(resultado));

numero:=numero+1;
end loop;

end;

Ingresemos el siguiente lote de comandos en el Oracle SQL Developer:

set serveroutput on;

execute dbms_output.enable (1000000);

declare

numero number:=0;

resultado number;

begin

while numero<=5 loop

resultado:=3*numero;

dbms_output.put_line('3*'||to_char(numero)||'='||to_char(resultado));

numero:=numero+1;

end loop;

end;

También podría gustarte