You are on page 1of 16

Apuntes de Bases de Datos II

15/09/15

Triggers (Disparadores)
En PostgreSQL, los triggers son funciones que pueden ser escritas en cualquier lenguaje
procedural como PL/pgSQL, PL/Tcl, PL/Perl y PL/Python. Actualmente no es posible escribir un
trigger directamente en lenguaje SQL.
Un trigger o disparador es una accin definida en una tabla de la base de datos y ejecutada
automticamente por una funcin programada por el DBA o el programador. Esta accin se
activar, segn se haya definido, cuando se realice un INSERT, un UPDATE un DELETE en la
tabla mencionada.
Un disparador se puede definir de las siguientes maneras:
Para que ocurra ANTES de cualquier INSERT,UPDATE DELETE
Para que ocurra DESPUES de cualquier INSERT,UPDATE DELETE
Para que se ejecute una sola vez por comando SQL (statement-level trigger)
Para que se ejecute por cada fila afectada por un comando SQL (row-level trigger)
Esta es la sintaxis del comando SQL que se utiliza para definir un trigger en una tabla.
CREATE TRIGGER nombre { BEFORE | AFTER } { INSERT | UPDATE | DELETE
[ OR ... ] }
ON tabla [ FOR [ EACH ] { ROW | STATEMENT } ]

EXECUTE PROCEDURE nombre de funcion ( argumentos )


Antes de definir el trigger se tendr que definir el procedimiento almacenado que se ejecutar
cuando el disparador se active.
El procedimiento almacenado usado por nuestro trigger se puede programar en cualquiera de los
lenguajes de procedimientos disponibles, entre ellos, el proporcionado por default cuando se
instala PostgreSQL, el PL/pgSQL. Este lenguaje es el que se utilizar en todos los ejemplos.
Podr encontrar mas informacin sobre procedimientos almacenados en el artculo
"Procedimientos almacenados y PL/pgSQL"

Caractersticas y Reglas
A continuacin se mencionan algunas de las caractersticas y reglas ms importantes a
considerar, cuando se defina un trigger y/o se programe un procedimiento almacenado que sea
utilizado por un disparador:
1. El procedimiento almacenado que se vaya a utilizar por el trigger debe definirse e instalarse
antes de definir el propio disparador.
2. Un procedimiento que se vaya a utilizar por un trigger no puede tener argumentos y tiene
que devolver el tipo "trigger".
3. Un mismo procedimiento almacenado se puede utilizar por mltiples triggers en diferentes
tablas.
4. Procedimientos almacenados utilizados por disparadores que se ejecutan una sola vez por
comando SQL (statement-level) tienen que devolver siempre NULL.
Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

5. Procedimientos almacenados utilizados por triggers que se ejecutan una vez por fila
afectada por el comando SQL (row-level) pueden devolver una fila de tabla.
6. Procedimientos almacenados utilizados por triggers que se ejecutan una vez por fila
afectada por el comando SQL (row-level) y ANTES de ejecutar el comando SQL que lo
lanz, pueden:
1. Retornar NULL para saltarse la operacin en la fila afectada.
2. devolver una fila de tabla (RECORD)
7. Procedimientos almacenados utilizados por triggers que se ejecutan AFTER de ejecutar el
comando SQL que lo lanz, ignoran el valor de retorno, asi que pueden retornar NULL sin
problemas.
8. En resumen, independendientemente de cmo se defina un trigger, el procedimiento
almacenado utilizado por dicho disparador tiene que devolver bien NULL, bien un valor
RECORD con la misma estructura que la tabla que lanz dicho trigger.
9. Si una tabla tiene ms de un disparador definido para un mismo evento (INSERT, UPDATE,
DELETE), estos se ejecutarn en orden alfabtico por el nombre del trigger. En el caso de
disparadores del tipo BEFORE / row-level, la file retornada por cada disparador, se
convierte en la entrada del siguiente. Si alguno de ellos retorna NULL, la operacin ser
anulada para la fila afectada.
10.Procedimientos almacenados utilizados por disparadores pueden ejecutar sentencias SQL
que a su vez pueden activar otros disparadores. Esto se conoce como disparadores en
cascada. No existe lmite para el nmero de triggers que se pueden llamar pero es
responsabilidad del programador el evitar una recursin infinita de llamadas en la que un
disparador se llame asi mismo de manera recursiva.
Otra cosa que tenemos que tener en cuenta es que, por cada disparador que definamos en una
tabla, nuestra base de datos tendr que ejecutar la funcin asociada a dicho disparador. El uso de
triggers de manera incorrecta inefectiva puede afectar significativamente al rendimiento de
nuestra base de datos. Los principiantes deberian de usar un tiempo para entender cmo
funcionan y as poder hacer un uso correcto de los mismos antes de usarlos en sistemas en
produccin.

Variables especiales en PL/pgSQL


Cuando una funcin escrita en PL/pgSQL es llamada por un disparador tenemos ciertas variables
especiales disponibles en dicha funcin. Estas variables son las siguientes:
NEW. Tipo de dato RECORD; Variable que contiene la nueva fila de la tabla para las
operaciones INSERT/UPDATE en disparadores del tipo row-level. Esta variable es NULL en
disparadores del tipo statement-level.
OLD. Tipo de dato RECORD; Variable que contiene la antigua fila de la tabla para las
operaciones UPDATE/DELETE en disparadores del tipo row-level. Esta variable es NULL en
disparadores del tipo statement-level.
TG_NAME. Tipo de dato name; variable que contiene el nombre del disparador que est
usando la funcin actualmente.
Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

TG_WHEN. Tipo de dato text; una cadena de texto con el valor BEFORE o AFTER
dependiendo de como el disparador que est usando la funcin actualmente ha sido definido
TG_LEVEL. Tipo de dato text; una cadena de texto con el valor ROW o STATEMENT
dependiendo de como el disparador que est usando la funcin actualmente ha sido definido
TG_OP. Tipo de dato text; una cadena de texto con el valor INSERT, UPDATE o DELETE
dependiendo de la operacin que ha activado el disparador que est usando la funcin
actualmente.
TG_RELID. Tipo de dato oid; el identificador de objeto de la tabla que ha activado el
disparador que est usando la funcin actualmente.
TG_RELNAME. Tipo de dato name; el nombre de la tabla que ha activado el disparador que
est usando la funcin actualmente. Esta variable es obsoleta y puede desaparacer en el futuro.
Usar TG_TABLE_NAME.
TG_TABLE_NAME. Tipo de dato name; el nombre de la tabla que ha activado el disparador
que est usando la funcin actualmente.
TG_TABLE_SCHEMA. Tipo de dato name; el nombre de la schema de la tabla que ha
activado el disparador que est usando la funcin actualmente.
TG_NARGS. Tipo de dato integer; el nmero de argumentos dados al procedimiento en la
sentencia CREATE TRIGGER.
TG_ARGV[]. Tipo de dato text array; los argumentos de la sentencia CREATE TRIGGER. El
ndice empieza a contar desde 0. Indices invlidos (menores que 0 mayores/iguales que
tg_nargs) resultan en valores nulos.

Ejemplos
Una vez que hemos visto la teoria bsica de disparadores nada mejor que unos cuantos ejemplos
prcticos para ver como se usan y defininen los disparadores en PostgreSQL. (estos ejemplos han
sido comprobados en postgreSQL 9.1 y pgAdmin III v.1.14.2).
1. Ejecute pgAdmin III
Se abrir una ventana como la de la
derecha. Puede observar que es la
versin 9.1 y que hay tres bases de
datos (se usaron en ejercicios
anteriores).

El lenguaje PL/pgSQL est instalado


por default y lo puede comprobar
haciendo lo siguiente:
Establezca conexin con la base de
datos postgres dando clic sobre ella con el botn izquierdo y expanda su contenido. Vaya al

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

objeto Extensions y expndalo tambin, le mostrar que tiene


instalado el lenguaje plpgsql como ilustra la figura de la derecha.
2. Contraiga/colapse el contenido de la base de datos postgres y
seleccione la herramienta SQL para ejecutar consultas sobre esta
base de datos.
3. Escriba la sentencia que aparece en la imagen de abajo a la izquierda y en el output pane
obtendr un resultado similar al de la imagen de abajo a la derecha.

4. Cierre la herramienta SQL y en el panel Object browser seleccione


con el botn derecho el objecto Databases (3) y seleccione Refresh.
Le aparecer la nueva bases de datos test001 marcada con una x roja,
que indica que no tenemos conexin con ella.
Para establecer una conexin con la base de datos test001 slo de un
clic sobre ella con el botn izquierdo, y abra nuevamente la herramienta
SQL. Las sentencias que se escriban a continuacin afectarn slo a
esta base de datos.

5. escriba la sentencia que aparece en la


imagen a la derecha, tenga cuidado de
escribirla con sus comas, parntesis y
punto y como final.

Puede revisar el resultado de la sentencia en el output pane y


tambin en el object browser. Expanda la base de datos
test001 como ilustra la imagen de la izquierda y encontrar la
tabla numeros que se cre mediante la sentencia anterior.

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

En caso que no aparezca la tabla, seleccione el objeto Tablas con el botn derecho y seleccione
la opcin Refresh. Debera aparecer la tabla.
6. Despus tenemos que crear una funcin en PL/pgSQL para ser usada por nuestro disparador.
Nuestra primera funcin es la ms simple que se puede definir y lo nico que har es devolver el
valor NULL.

Puede ver en el object browser en el objeto Trigger Functions que ya


existe la funcin proteger_datos(). Compare esta imagen con la del
paso 5 y ver que inicialmente en este objeto haba cero (0) funciones
definidas.

7. A continuacin definimos en la tabla numeros un disparador/trigger del tipo BEFORE / row-level


para la operacin DELETE. Ms adelante veremos como funciona:

Como se dijo en un inicio, un trigger es una accin que se guarda en una tabla, as que puede
corroborar la ejecucin de la sentencia anterior si revisa en el object browser la tabla numeros y
observa el SQL pane
La figura siguiente muestra que como parte de la definicin de la tabla tenemos las columnas de la
tabla numeros ms el trigger que se estableci en este paso.

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

8. Ahora vamos a definir una nueva funcin un poco ms complicada y un nuevo disparador en
nuestra tabla numeros.

En el object browser2 puede ver que en el objeto Trigger Functions


ahora hay dos funciones, proteger_datos y rellenar_datos.
9. Cree el nuevo trigger rellenar_datos y revse su ejecucin en la tabla
test001.

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

Los triggers de la tabla numeros se muestran en


la figura de la izquierda

10. Ahora vamos a ver cmo funcionan los


triggers que se definieron en la tabla numeros.
En la herramienta SQL introduzca la siguiente
sentencia
SELECT * from numeros;
El output pane mostrar slo los nombres de las
columnas que tiene la tabla numeros.

11. Ejecute una por una cada sentencia siguiente

12. Vuelva a ejecutar la sentencia


SELECT * from numeros;

Si bien, slo se introdujeron valores en la columna numero, note que el resto de las columnas
tienen sus propios valores. Esto se debe al
funcionamiento de los triggers y de los stored
procedures - procedimientos almacenados.

13. Teclee y revise el funcionamiento de la siguiente


sentencia.

Al ejecutar nuevamente la sentencia SELECT * from numeros; vemos que el valor de 3 en la


columna de numero fue sustituido por un valor de 4 y sus respectivos valores de acuerdo a los
triggers y los procedimientos almacenados.
Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

Hemos realizado 2 INSERT y 1 UPDATE. Esto


significa que por cada uno de estos comandos el
sistema ha ejecutado la funcin rellenar_datos(),
una vez por cada fila afectada y antes de actualizar
la tabla numeros.
Habr comprobado que solamente se ha
actualizado la columna numero, pero al mostrar el contenido de la tabla numeros se puede
advertir que el resto de columnas (cuadrado, cubo, raiz2 y raiz3) tambin contienen valores.
De esta actualizacin se ha encargado la funcin rellenar_datos() llamada por nuestro
disparador. Vamos a analizar lo que hace esta funcin:
NEW.cuadrado := power(NEW.numero,2);
NEW.cubo := power(NEW.numero,3);
NEW.raiz2 := sqrt(NEW.numero);
NEW.raiz3 := cbrt(NEW.numero);
RETURN NEW;

Cuando ejecutamos el primer INSERT (numero = 3), el disparador rellenar_datos llama a


la funcin rellenar_datos() una vez.
El valor de la variable NEW al empezar a ejecutarse rellenar_datos() es numero=3,
cuadrado=NULL, cubo=NULL, raiz2=NULL, raiz3=NULL.
Nuestra tabla todavia no contiene ninguna fila.
A continuacin calculamos el cuadrado, el cubo, la raiz cuadrada y la raiz cubica de 3 y
asignamos estos valores a NEW.cuadrado, NEW.cubo, NEW.raiz2 y NEW.raiz3.
El valor de la variable NEW antes de la sentencia RETURN NEW es ahora numero=3,
cuadrado=9, cubo=27, raiz2=1.7320, raiz3=1.44225.
Con la sentencia RETURN NEW, retornamos la fila (RECORD) almacenada en la variable
NEW, y salimos de la funcin rellenar_datos(). El sistema almacena entonces el RECORD
contenido en NEW en la tabla numeros

14. De la misma manera funciona el disparador proteger_datos cuando ejecutamos una


sentencia DELETE, antes de borrar algo ejecutar la funcin
proteger_datos().
Esta funcin retorna el valor NULL y esto significa, segun la regla 6.1
definida en Caractersticas y Reglas lineas arriba, que para la fila
afectada no se ejecutar el comanado DELETE. Por eso y mientras este disparador este instalado
ser imposible de borrar algo de la tabla
numeros.

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

15. Vamos a continuar complicando las cosas.


Primero, vamos a desinstalar nuestros dos
disparadores proteger_datos y rellenar_datos.

16. A continuacin crearemos un disparador nico para las sentencias INSERT, UPDATE y
DELETE. Este nuevo disparador
utilizar una nueva funcin a la que
llamaremos proteger_y_rellenar_datos
(figura de la izquierda) en la que
tendremos que tomar en cuenta qu
tipo de comando ha activado el
disparador, si queremos retornar el
valor correcto. Para ello utilizaremos la
variable TG_OP.

El trigger se muestra en la figura de


abajo.

Valentn Belisario Domnguez Vera

Apuntes de Bases de Datos II

15/09/15

La definicin de la tabla la podemos


ver en el SQL pane del pgAdmin III, y
se muestra en la figura de la derecha.

Y todo seguir funcionando de la


misma manera que con los dos
disparadores del comienzo. Verifquelo realizando las siguientes acciones en el pgAdmin III.
17. muestre el contenido de toda la tabla

El resultado se muestra abajo a la derecha

18. Inserte en la tabla los valores 6 y 7

19. muestre nuevamente el contenido de la tabla. Deben


aparecer los valores iniciales adems de los valores
introducidos recientemente con sus clculos respectivos.

Valentn Belisario Domnguez Vera

10

Apuntes de Bases de Datos II

15/09/15

20. Ahora haga una actualizacin del registro que


tiene el valor de 12, pngale 10.

21. Muestre nuevamente el contenido de la tabla.


El registro actualizado se correr a la parte baja de
la tabla y los registros actualizados se corrern
una posicin hacia arriba, tal y como lo muestra la
imagen a la izquierda.

22. Por ltimo, intente hacer la eliminacin de un registro, puede ser cualquiera aunque se
escoger el que tiene el valor de 4.

23. El resultado muestra que ninguna fila fue


afectada, para comprobarlo, muestre el contenido de la tabla. El resultado debe ser similar al
obtenido anteriormente.

Valentn Belisario Domnguez Vera

11

Apuntes de Bases de Datos II

15/09/15

Todas las actividades realizadas tambin se pueden hacer en modo comando en la herramienta
denominada SQL shell que es uno de los programas del PostgreSQL

Cuando se ejecuta el SQL shell aparecer una ventana similar a la de arriba, en la que se deber
aceptar las propuestas que hace.
La aplicacin le informa si se desea conectar al Server [localhost], presione [enter].
Luego cuestiona si se desea conectar con la base de datos [postgres], presione [enter].
Le pregunta si el puerto es [5432], presione [enter].
Finalmente se le introduce el username [postgres], presione [enter].
Si la contrasea del username, la tiene guardada la aplicacin, ya no se solicitar; pero si no tiene
la contrasea guardada, entonces hay que teclearla y presionar [enter].
Introduzca los comandos mostrados en la siguiente figura

Valentn Belisario Domnguez Vera

12

Apuntes de Bases de Datos II

15/09/15

El primero es para crear la base de datos test002 y el segundo es para hacer la conexin a dicha
base de datos. El lenguaje plpgsql est instalado por default. En caso que no sea as, se introduce
el siguiente comando
Ahora se proceder a crear la tabla numeros.

Para crear la primera funcin se introduce lo siguiente.

Y se crea el trigger respectivo

para ver la definicin de la tabla, se introduce...

Se escribe la funcin para actualizar las columnas cuadrado, cubo, raiz2 y raiz3

Valentn Belisario Domnguez Vera

13

Apuntes de Bases de Datos II

15/09/15

y el disparador que actuar sobre la tabla

Al revisar la definicin de la tabla se observa que se ha agregado el segundo trigger, como lo


muestra la siguiente imagen

Es hora de probar el funcionamiento de las funciones y los triggers. Muestre el contenido de la


tabla numeros.

Ahora inserte los valores 2 y 3.

Valentn Belisario Domnguez Vera

14

Apuntes de Bases de Datos II

15/09/15

Vuelva a mostrar el contenido de la tabla, debe ser similar a la siguiente imagen.

Ahora haga una actualizacin, el registro con el valor 2, cmbielo a 4.

Vuelva a mostrar el contenido de la tabla, debe ser similar a la siguiente imagen.

Por ltimo, intente hacer el borrado de un registro.

Si despliega nuevamente el contenido de la tabla, se mostrar sin cambio alguno ya que el trigger
proteger_datos est evitando que se borre algo de la tabla.
Si compara esta parte con la seccin que se hizo en el pgAdmin III, observar que son las mismas
instrucciones slo que ahora se est trabajando en modo comando.
Para salir del modo comando se introduce el comando \q
ACTIVIDAD1: Se deja como actividad al estudiante realizar a partir del paso 15 en la que se
eliminan los dos triggers, se crea la funcin combinada proteger_y_rellenar_datos con su trigger
respectivo, y volver a revisar el funcionamiento insertando nuevos valores e intentando borrar
algn registro.
ACTIVIDAD2: La puede realizar en modo grfico (pgAdmin III) o en modo comandos (SQL shell).
1. Cree una base de datos llamada facturas y una tabla que se llame detalle_fac que tenga
los campos relativos a cdigo de producto, precio unitario, cantidad de piezas, subtotal
(resultado de multiplicar la cantidad de piezas por el precio unitario), iva (resultado de

Valentn Belisario Domnguez Vera

15

Apuntes de Bases de Datos II

15/09/15

multiplicar el subtotal por el 16%), total (suma del subtotal y el iva). Haga que la llave
primaria sea la columna cdigo de producto.
2. Usted debe seleccionar los tipos de datos ms apropiados para cada campo o columna.
3. Inserte los siguientes datos slo en las columnas relativas a cdigo de producto, cantidad
de piezas y precio unitario.
4. Primer registro: 100, 2 y $10.50
5. Segundo registro: 110, 3 y $3.33
6. Haga un desplegado de todos los campos para ver la informacin de la tabla. Slo deben
aparecer datos en las tres primeras columnas y primeros dos registros.
7. Cree la(s) funcion(es) y trigger(s) que necesite para calcular el subtotal, el iva y el total.
8. Inserte los siguientes datos slo en las columnas relativas a cantidad de piezas y precio
unitario.
9. Tercer registro: 120, 5 y $1.50
10. Cuarto registro: 130, 4 y $2.25
11. Haga un desplegado de todos los campos para ver la informacin de la tabla. Ahora deben
aparecer datos en cuatro registros. Los primeros dos slo deben tener datos en las
primeras tres columnas. Los siguientes dos registros deben tener datos en todas las
columnas.

Fuente:
http://www.postgresql.org.es/node/301 , artculo del 11/06/2009, por usuario: rafaelma
revisada en Agosto/2012

Valentn Belisario Domnguez Vera

16

You might also like