Una de las funcionalidades disponibles en Postre!"# son los denominados disparadores $triers%& 'n este art(culo )amos a introducirnos en el mundo de los disparadores, como funcionan * como podemos empe+ar a utili+arlos& Un disparador no es otra cosa ,ue una acci-n definida en una tabla de nuestra base de datos * e.ecutada autom/ticamente por una funci-n proramada por nosotros& 'sta acci-n se acti)ar/, seun la definamos, cuando realicemos un 01!'23, un UP453' - un 4'#'3' en la susodic6a tabla& Un disparador se puede definir de las siuientes maneras: Para ,ue ocurra 513'! de cual,uier 01!'23,UP453' - 4'#'3' Para ,ue ocurra 4'!PU'! de cual,uier 01!'23,UP453' - 4'#'3' Para ,ue se e.ecute una sola )e+ por comando !"# $statement-le)el trier% Para ,ue se e.ecute por cada linea afectada por un comando !"# $row-le)el trier% 'sta es la definici-n del comando !"# ,ue se puede utili+ar para definir un disparador en una tabla& CREATE TRIGGER nombre { BEFORE | AFTER } { INSERT | UPDATE | DELETE [ OR ... ] } ON taba [ FOR [ EAC! ] { RO" | STATE#ENT } ] E$ECUTE PROCEDURE nombre %e &'n()on * ar+'mento, - 5ntes de definir el disparador tendremos ,ue definir el procedimiento almacenado ,ue se e.ecutar/ cuando nuestro disparador se acti)e& 'l procedimiento almacenado usado por nuestro disparador se puede proramar en cual,uiera de los lenua.es de procedimientos disponibles, entre ellos, el proporcionado por defecto cuando se instala Postre!"#, P#/p!"#& 'ste lenua.e es el ,ue utili+aremos en todos los e.emplos de este /rticulo& Podeis encontrar mas informaci-n sobre procedimientos almacenados en el art(culo "Procedimientos almacenados y PL/pgSQL" Caractersticas y reglas a seguir 5 continuaci-n teneis alunas de las caracter(sticas * relas m/s importantes a tener en cuenta, cuando definamos un disparador */- proramemos un procedimiento almacenado ,ue se )a*a a utili+ar por un disparador: 1& 'l procedimiento almacenado ,ue se )a*a a utili+ar por el disparador debe de definirse e instalarse antes de definir el propio disparador&
2& Un procedimiento ,ue se )a*a a utili+ar por un disparador no puede tener arumentos * tiene ,ue de)ol)er el tipo 7trier7&
8& Un mismo procedimiento almacenado se puede utili+ar por m9ltiples disparadores en diferentes tablas&
:& Procedimientos almacenados utili+ados por disparadores ,ue se e.ecutan una sola )e+ per comando !"# $statement-le)el% tienen ,ue de)ol)er siempre 1U##&
;& Procedimientos almacenados utili+ados por disparadores ,ue se e.ecutan una )e+ per linea afectada por el comando !"# $row-le)el% pueden de)ol)er una fila de tabla&
6& Procedimientos almacenados utili+ados por disparadores ,ue se e.ecutan una )e+ per fila afectada por el comando !"# $row-le)el% * 513'! de e.ecutar el comando !"# ,ue lo lan+-, pueden: 1& 2etornar 1U## para saltarse la operaci-n en la fila afectada& 2& < de)ol)er una fila de tabla $2'=>24%
?& Procedimientos almacenados utili+ados por disparadores ,ue se e.ecutan 4'!PU'! de e.ecutar el comando !"# ,ue lo lan+-, inoran el )alor de retorno, asi ,ue pueden retornar 1U## sin problemas&
@& 'n resumen, independendientemente de como se defina un disparador, el procedimiento almacenado utili+ado por dic6o disparador tiene ,ue de)ol)er - bien 1U##, - bien un )alor 2'=>24 con la misma estructura ,ue la tabla ,ue lan+- dic6o disparador&
9& !i una tabla tiene m/s de un disparador definido para un mismo e)ento $01!'23,UP453',4'#'3'%, estos se e.ecutar/n en orden alfabAtico por el nombre del disparador& 'n el caso de disparadores del tipo 513'! / row-le)el, la file retornada por cada disparador, se con)ierte en la entrada del siuiente& !i aluno de ellos retorna 1U##, la operaci-n ser/ anulada para la fila afectada&
10& Procedimientos almacenados utili+ados por disparadores pueden e.ecutar sentencias !"# ,ue a su )e+ pueden acti)ar otros disparadores& 'sto se conoce como disparadores en cascada& 1o eBiste l(mite para el n9mero de disparadores ,ue se pueden llamar pero es responsabilidad del proramador el e)itar una recursi-n infinita de llamadas en la ,ue un disparador se llame asi mismo de manera recursi)a& >tra cosa ,ue tenemos ,ue tener en cuenta es ,ue, por cada disparador ,ue definamos en una tabla, nuestra base de datos tendr/ ,ue e.ecutar la funci-n asociada a dic6o disparador& 'l uso de disparadores de manera incorrecta - inefecti)a puede afectar sinificati)amente al rendimiento de nuestra base de datos& #os principiantes deberian de usar un tiempo para entender como funcionan * asi poder 6acer un uso correcto de los mismos antes de usarlos en sistemas en producci-n& Variables especiales en PL/pgSQL =uando una funci-n escrita en P#/p!"# es llamada por un disparador tenemos ciertas )ariable especiales disponibles en dic6a funci-n& 'stas )ariables son las siuientes: 1'C 3ipo de dato 2'=>24D Eariable ,ue contiene la nue)a fila de la tabla para las operaciones 01!'23/UP453' en disparadores del tipo row-le)el& 'sta )ariable es 1U## en disparadores del tipo statement-le)el& >#4 3ipo de dato 2'=>24D Eariable ,ue contiene la antiua fila de la tabla para las operaciones UP453'/4'#'3' en disparadores del tipo row-le)el& 'sta )ariable es 1U## en disparadores del tipo statement-le)el& 3FG15H' 3ipo de dato nameD )ariable ,ue contiene el nombre del disparador ,ue est/ usando la funci-n actualmente& 3FGCI'1 3ipo de dato teBtD una cadena de teBto con el )alor J'K>2' o 5K3'2 dependiendo de como el disparador ,ue est/ usando la funci-n actualmente 6a sido definido 3FG#'E'# 3ipo de dato teBtD una cadena de teBto con el )alor 2>C o !353'H'13 dependiendo de como el disparador ,ue est/ usando la funci-n actualmente 6a sido definido 3FG>P 3ipo de dato teBtD una cadena de teBto con el )alor 01!'23, UP453' o 4'#'3' dependiendo de la operaci-n ,ue 6a acti)ado el disparador ,ue est/ usando la funci-n actualmente& 3FG2'#04 3ipo de dato oidD el identificador de ob.eto de la tabla ,ue 6a acti)ado el disparador ,ue est/ usando la funci-n actualmente& 3FG2'#15H' 3ipo de dato nameD el nombre de la tabla ,ue 6a acti)ado el disparador ,ue est/ usando la funci-n actualmente& 'sta )ariable es obsoleta * puede desaparacer en el futuro& Usar 3FG35J#'G15H'& 3FG35J#'G15H' 3ipo de dato nameD el nombre de la tabla ,ue 6a acti)ado el disparador ,ue est/ usando la funci-n actualmente& 3FG35J#'G!=I'H5 3ipo de dato nameD el nombre de la sc6ema de la tabla ,ue 6a acti)ado el disparador ,ue est/ usando la funci-n actualmente& 3FG152F! 3ipo de dato inteerD el n9mero de arumentos dados al procedimiento en la sentencia =2'53' 320FF'2& 3FG52FELM 3ipo de dato teBt arra*D los arumentos de la sentencia =2'53' 320FF'2& 'l (ndice empie+a a contar desde 0& 0ndices in)/lidos $menores ,ue 0 - ma*ores/iuales ,ue tGnars% resultan en )alores nulos& Ejemplos prcticos Una )e+ ,ue 6emos )isto la teoria b/sica de disparadores nada me.or ,ue unos cuantos e.emplos pr/cticos para )er como se usan * defininen los disparadores en Postre!"#& $estos e.emplos 6an sido comprobados en postre!"# @&8&?%& =reamos una base de datos para utili+arla con nuestros e.emplos: .o,t+re,/,er0er123 .,4 "e(ome to .,4 5.6.78 t9e Po,t+reS:L )ntera(t)0e term)na. T;.e1 <(o.;r)+9t &or %),tr)b't)on term, <9 &or 9e. =)t9 S:L (omman%, <> &or 9e. =)t9 .,4 (omman%, <+ or term)nate =)t9 ,em)(oon to e?e('te 4'er; <4 to 4')t .o,t+re,@A CREATE DATABASE te,tBBCD CREATE DATABASE .o,t+re,@A <( te,tBBC Eo' are no= (onne(te% to %ataba,e Fte,tBBCF. te,tBBC@A #o pr(mero ,ue tenemos ,ue 6acer es instalar el lenua.e plps,l si no lo tenemos instalado& CREATE PROCEDURAL LANGUAGE ..+,4D 56ora creamos una tabla para poder definir nuestro primer disparador: CREATE TABLE n'mero,* n'mero b)+)nt NOT NULL8 ('a%ra%o b)+)nt8 ('bo b)+)nt8 ra)GH rea8 ra)G6 rea8 PRI#ARE IEE *n'mero- -D 4espuAs tenemos ,ue crear una funci-n en P#/p!"# para ser usada por nuestro disparador& 1uestra primera funci-n es la m/s simple ,ue se puede definir * lo 9nico ,ue 6ar/ ser/ de)ol)er el )alor 1U##: CREATE OR REPLACE FUNCTION .rote+erJ%ato,*- RETURNS TRIGGER AS 3.rote+erJ%ato,3 DECLARE BEGIN
KK KK E,ta &'n()on e, ',a%a .ara .rote+er %ato, en 'n taba KK No ,e .erm)t)ra e borra%o %e &)a, ,) a ',amo, KK en 'n %),.ara%or %e t).o BEFORE L ro=Ke0e KK RETURN NULLD ENDD 3.rote+erJ%ato,3 LANGUAGE ..+,4D 5 continuaci-n definimos en la tabla numeros un disparador del tipo J'K>2' / row-le)el para la operaci-n 4'#'3'& H/s adelante )eremos como funciona: CREATE TRIGGER .rote+erJ%ato, BEFORE DELETE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ%ato,*-D #a definici-n de nuestra tabla 6a ,uedado asi: te,tBBC@A <% n'mero, Tabe F.'b)(.n'mero,F Co'mn | T;.e | #o%)&)er, KKKKKKKKKKMKKKKKKKKMKKKKKKKKKKK n'mero | b)+)nt | not n' ('a%ra%o | b)+)nt | ('bo | b)+)nt | ra)GH | rea | ra)G6 | rea | In%e?e,1 Fn'mero,J.Ne;F PRI#ARE IEE8 btree *n'mero- Tr)++er,1 .rote+erJ%ato, BEFORE DELETE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ%ato,*- 56ora )amos a definir una nue)a funci-n un poco m/s complicada * un nue)o disparador en nuestra tabla numeros: CREATE OR REPLACE FUNCTION reenarJ%ato,*- RETURNS TRIGGER AS 3reenarJ%ato,3 DECLARE BEGIN
NE".('a%ra%o 1@ .o=er*NE".n'mero8H-D NE".('bo 1@ .o=er*NE".n'mero86-D NE".ra)GH 1@ ,4rt*NE".n'mero-D NE".ra)G6 1@ (brt*NE".n'mero-D RETURN NE"D ENDD 3reenarJ%ato,3 LANGUAGE ..+,4D CREATE TRIGGER reenarJ%ato, BEFORE INSERT OR UPDATE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE reenarJ%ato,*-D #a definici-n de nuestra tabla 6a ,uedado asi: te,tBBC@A <% n'mero, Tabe F.'b)(.n'mero,F Co'mn | T;.e | #o%)&)er, KKKKKKKKKKMKKKKKKKKMKKKKKKKKKKK n'mero | b)+)nt | not n' ('a%ra%o | b)+)nt | ('bo | b)+)nt | ra)GH | rea | ra)G6 | rea | In%e?e,1 Fn'mero,J.Ne;F PRI#ARE IEE8 btree *n'mero- Tr)++er,1 .rote+erJ%ato, BEFORE DELETE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ%ato,*- reenarJ%ato, BEFORE INSERT OR UPDATE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE reenarJ%ato,*- 56ora )amos a )er como los disparadores ,ue 6emos definido en la tabla numeros funcionan: te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKMKKKKKKK *B ro=,- te,tBBC@A INSERT INTO numeros (numero) VALUES (2); INSERT B C te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH *C ro=,- te,tBBC@A INSERT INTO numeros (numero) VALUES (3); INSERT B C te,tBBC@A SELECT R &rom n'mero,D n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH 6 | Q | H7 | C.76HBP | C.OOHHP *H ro=,- te,tBBC@A UPDATE numeros SET numero = 4 !ERE numero = 3; UPDATE C te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O *H ro=,- Iemos reali+ado 2 01!'23 * 1 UP453'& 'sto sinifica ,ue por cada uno de estos comandos el sistema 6a e.ecutado la funci-n rellenar_datos(), una )e+ por cada fila afectada * antes de actuali+ar la tabla numeros& =omo podeis comprobar, nosotros solamente 6emos actuali+ado la columna numero, pero al listar el contenido de nuestra tabla )emos como el resto de columnas $cuadrado, cubo, raiz2 * raiz3% tambien contienen )alores& 4e esta actuali+aci-n se 6a encarado la funci-n rellenar_datos() llamada por nuestro disparador& Eamos a anali+ar lo ,ue 6ace esta funci-n: NE".('a%ra%o 1@ .o=er*NE".n'mero8H-D NE".('bo 1@ .o=er*NE".n'mero86-D NE".ra)GH 1@ ,4rt*NE".n'mero-D NE".ra)G6 1@ (brt*NE".n'mero-D RETURN NE"D =uando e.ecutamos el primer 01!'23 $numero N 2%, el disparador rellenar_datos llama a la funci-n rellenar_datos() una )e+&
'l )alor de la )ariable 1'C al empe+ar a e.ecutarse rellenar_datos() es numeroN2, cuadradoN1U##, cuboN1U##, rai+2N1U##, rai+8N1U##&
1uestra tabla toda)ia no contiene ninuna fila&
5 continuaci-n calculamos el cuadrado, el cubo, la rai+ cuadrada * la rai+ cubica de 2 * asinamos estos )alores a 1'C&cuadrado, 1'C&cubo, 1'C&rai+2 * 1'C&rai+8&
'l )alor de la )ariable 1'C antes de la sentencia 2'3U21 1'C es a6ora numeroN2, cuadradoN:, cuboN@, rai+2N1&:1:21, rai+8N1&2;992&
=on la sentencia 2'3U21 1'C, retornamos la fila $2'=>24% almacenada en la )ariable 1'C, * salimos de la funci-n rellenar_datos()& 'l sistema almacena entonces el 2'=>24 contenido en 1'C en la tabla numeros =omo podeis )er, todo mu* l-ico& 4e la misma manera funciona el disparador proteger_datos cuando e.ecutamos una sentencia 4'#'3'& 5ntes de borrar nada e.ecutar/ la funci-n proteger_datos()& 'sta funci-n retorna el )alor 1U## * esto sinifica, seun la rela 6&1 definida en este art(culo, ,ue para la fila afectada no se e.ecutar/ el comanado 4'#'3'& Por eso * mientras este disparador este instalado ser/ imposible de borrar nada de la tabla numeros& te,tBBC@A DELETE "RO# numeros; DELETE B te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O *H ro=,- Eamos a continuar complicando las cosas& Primero, )amos a desinstalar nuestros dos disparadores proteger_datos * rellenar_datos& te,tBBC@A DROP TRIGGER .rote+erJ%ato, ON n'mero,D DROP TRIGGER te,tBBC@A DROP TRIGGER reenarJ%ato, ON n'mero,D DROP TRIGGER 5 continuaci-n crearemos un disparador 9nico para las sentencias 01!'23, UP453' * 4'#'3'& 'ste nue)o disparador utili+ar/ una nue)a funci-n en la ,ue tendremos ,ue tener en cuenta ,ue tipo de comando 6a acti)ado el disparador, si ,ueremos retornar el )alor correcto& Para ello utili+aremos la )ariable 3FG>P& CREATE OR REPLACE FUNCTION .rote+erJ;JreenarJ%ato,*- RETURNS TRIGGER AS 3.rote+erJ;JreenarJ%ato,3 DECLARE BEGIN IF *TGJOP @ TINSERTT OR TGJOP @ TUPDATET - T!EN NE".('a%ra%o 1@ .o=er*NE".n'mero8H-D NE".('bo 1@ .o=er*NE".n'mero86-D NE".ra)GH 1@ ,4rt*NE".n'mero-D NE".ra)G6 1@ (brt*NE".n'mero-D RETURN NE"D
ELSEIF *TGJOP @ TDELETET- T!EN RETURN NULLD
END IFD ENDD 3.rote+erJ;JreenarJ%ato,3 LANGUAGE ..+,4D CREATE TRIGGER .rote+erJ;JreenarJ%ato, BEFORE INSERT OR UPDATE OR DELETE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ;JreenarJ%ato,*-D #a definici-n de nuestra tabla 6a ,uedado asi: te,tBBC@A <% n'mero, Tabe F.'b)(.n'mero,F Co'mn | T;.e | #o%)&)er, KKKKKKKKKKMKKKKKKKKMKKKKKKKKKKK n'mero | b)+)nt | not n' ('a%ra%o | b)+)nt | ('bo | b)+)nt | ra)GH | rea | ra)G6 | rea | In%e?e,1 Fn'mero,J.Ne;F PRI#ARE IEE8 btree *n'mero- Tr)++er,1 reenarJ%ato, BEFORE INSERT OR DELETE OR UPDATE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ;JreenarJ%ato,*- O todo seuir/ funcionando de la misma manera ,ue con los dos disparadores del comien+o: te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O *H ro=,- te,tBBC@A INSERT INTO numeros (numero) VALUES ($); INSERT B C te,tBBC@A INSERT INTO numeros (numero) VALUES (%); INSERT B C te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 S | 6S | HCS | H.OOQOQ | C.5C7CH *O ro=,- te,tBBC@A UPDATE numeros SET numero = &' !ERE numero = %; UPDATE C te,tBBC@A SELECT * from numeros ; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 CB | CBB | CBBB | 6.CSHH5 | H.CPOO6 *O ro=,- te,tBBC@A DELETE "RO# numeros ()ere numero =&'; DELETE B te,tBBC@A SELECT * from numeros; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 CB | CBB | CBBB | 6.CSHH5 | H.CPOO6 *O ro=,- Por 9ltimo * antes de terminar, )amos a definir un disparador del tipo statement-le)el ,ue se e.ecute despues de nuestras sentencias 01!'23, UP453' * 4'#'3'& #a funci-n e.ecutada por este disparador rabar/ datos de la e.ecuci-n en la tabla cambios $esto no sir)e para muc6o en la )ida real, pero como e.emplo esta bien para ,ue )eais como funciona% Para demostrar como podemos utili+ar esto )amos a definir una nue)a tabla: CREATE TABLE (amb)o,* t)me,tam.J TI#ESTA#P "IT! TI#E UONE %e&a't NO"*-8 nombreJ%),.ara%or te?t8 t).oJ%),.ara%or te?t8 n)0eJ%),.ara%or te?t8 (oman%o te?t -D #a funci-n la podemos definir asi: CREATE OR REPLACE FUNCTION +rabarJo.era()one,*- RETURNS TRIGGER AS 3+rabarJo.era()one,3 DECLARE BEGIN
INSERT INTO (amb)o, * nombreJ%),.ara%or8 t).oJ%),.ara%or8 n)0eJ%),.ara%or8 (oman%o- VALUES * TGJNA#E8 TGJ"!EN8 TGJLEVEL8 TGJOP -D RETURN NULLD ENDD 3+rabarJo.era()one,3 LANGUAGE ..+,4D O el disparador lo instalariamos de la siuiente forma: CREATE TRIGGER +rabarJo.era()one, AFTER INSERT OR UPDATE OR DELETE ON n'mero, FOR EAC! STATE#ENT E$ECUTE PROCEDURE +rabarJo.era()one,*-D #a definici-n de nuestra tabla ,uedaria asi: te,tBBC@A <% n'mero,D Tabe F.'b)(.n'mero,F Co'mn | T;.e | #o%)&)er, KKKKKKKKKKMKKKKKKKKMKKKKKKKKKKK n'mero | b)+)nt | not n' ('a%ra%o | b)+)nt | ('bo | b)+)nt | ra)GH | rea | ra)G6 | rea | In%e?e,1 Fn'mero,J.Ne;F PRI#ARE IEE8 btree *n'mero- Tr)++er,1 +rabarJo.era()one, AFTER INSERT OR DELETE OR UPDATE ON n'mero, FOR EAC! STATE#ENT E$ECUTE PROCEDURE +rabarJo.era()one,*- .rote+erJ;JreenarJ%ato, BEFORE INSERT OR DELETE OR UPDATE ON n'mero, FOR EAC! RO" E$ECUTE PROCEDURE .rote+erJ;JreenarJ%ato,*- 5 continuaci-n podeis )er como funcionaria: te,tBBC@A SELECT * from *+m,-os ; t)me,tam.J | nombreJ%),.ara%or | t).oJ%),.ara%or | n)0eJ%),.ara%or | (oman%o KKKKKKKKKKKKMKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKKK MKKKKKKKKK *B ro=,- te,tBBC@A INSERT INTO numeros (numero) VALUES (&''); INSERT B C te,tBBC@A SELECT * from numeros ; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 CB | CBB | CBBB | 6.CSHH5 | H.CPOO6 CBB | CBBBB | CBBBBBB | CB | O.SOCPQ *P ro=,- te,tBBC@A SELECT * from *+m,-os ; t)me,tam.J | nombreJ%),.ara%or | t).oJ%),.ara%or | n)0eJ%),.ara%or | (oman%o KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKK MKKKKKKKKKKKKKKKKKKMKKKKKKKKK HBBQKBSKCC H61BP1HQ.7QOP6OMBH | +rabarJo.era()one, | AFTER | STATE#ENT | INSERT *C ro=- te,tBBC@A UPDATE numeros SET numero = &''' !ERE numero = &''; UPDATE C te,tBBC@A SELECT * from numeros ; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 CB | CBB | CBBB | 6.CSHH5 | H.CPOO6 CBBB | CBBBBBB | CBBBBBBBBB | 6C.SHH5 | CB *P ro=,- te,tBBC@A SELECT * from *+m,-os ; t)me,tam.J | nombreJ%),.ara%or | t).oJ%),.ara%or | n)0eJ%),.ara%or | (oman%o KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKK MKKKKKKKKKKKKKKKKKKMKKKKKKKKK HBBQKBSKCC H61BP1HQ.7QOP6OMBH | +rabarJo.era()one, | AFTER | STATE#ENT | INSERT HBBQKBSKCC H61BS1B5.HPQOHCMBH | +rabarJo.era()one, | AFTER | STATE#ENT | UPDATE *H ro=,- te,tBBC@A DELETE "RO# numeros ()ere numero =&'''; DELETE B te,tBBC@A SELECT * from numeros ; n'mero | ('a%ra%o | ('bo | ra)GH | ra)G6 KKKKKKKKMKKKKKKKKKKMKKKKKKKKKKKKMKKKKKKKKKMKKKKKKKKK H | O | 5 | C.OCOHC | C.HPQQH O | CS | SO | H | C.P57O P | HP | CHP | H.H6SB7 | C.7BQQ5 CB | CBB | CBBB | 6.CSHH5 | H.CPOO6 CBBB | CBBBBBB | CBBBBBBBBB | 6C.SHH5 | CB *P ro=,- te,tBBC@A SELECT * from *+m,-os ; t)me,tam.J | nombreJ%),.ara%or | t).oJ%),.ara%or | n)0eJ%),.ara%or | (oman%o KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKKKKKMKKKKKKKKKKKKKKKKK MKKKKKKKKKKKKKKKKKKMKKKKKKKKK HBBQKBSKCC H61BP1HQ.7QOP6OMBH | +rabarJo.era()one, | AFTER | STATE#ENT | INSERT HBBQKBSKCC H61BS1B5.HPQOHCMBH | +rabarJo.era()one, | AFTER | STATE#ENT | UPDATE HBBQKBSKCC H61BS1HS.PS5S6HMBH | +rabarJo.era()one, | AFTER | STATE#ENT | DELETE *6 ro=,- O con este 9ltimo e.emplo, terminamos este art(culo sobre disparadores en Postre!"#& !olamente os ,ueda practicar, leer la documentaci-n * usar )uestra imainaci-n