Está en la página 1de 26

ASGBD. Unidad 4. Automatización de tareas. Scripts.

Unidad 4. Automatización de Tareas. Scripts.


1.- Vistas y transacciones. _________________________________________________________ 3
2.- Procedimientos Almacenados.___________________________________________________ 4
Creación de un procedimiento sencillo. __________________________________________________ 5
Llamada a un procedimiento. __________________________________________________________ 5
Consultar información sobre los procedimientos creados en la base de datos. __________________ 5
Consultar código almacenado en un procedimiento. _______________________________________ 5
Eliminación de un procedimiento. ______________________________________________________ 5
3.- Uso de variables. _____________________________________________________________ 6
Asignación de valores a una variable ____________________________________________________ 6
4.- Delimitadores ________________________________________________________________ 6
5.- Creación de un procedimiento elaborado con parámetros de entrada y salida. ____________ 7
6.- Estructuras de control de flujo __________________________________________________ 8
Estructuras condicionales. La estructura IF. _____________________________________________ 8
Estructuras condicionales. La estructura CASE. __________________________________________ 9
7.- Estructuras de repetición. ______________________________________________________ 9
La estructura LOOP … ITERATE… LEAVE ___________________________________________ 9
La estructura REPEAT …UNTIL… END REPEAT _____________________________________ 10
La estructura WHILE…DO… END WHILE ___________________________________________ 11
8.- Funciones __________________________________________________________________ 12
Creación de funciones. _______________________________________________________________ 12
Consultar información sobre las funciones creadas en la base de datos. ______________________ 12
Consultar código almacenado en una función. ___________________________________________ 13
Eliminación de una función. __________________________________________________________ 13
9.- Cursores ___________________________________________________________________ 13
Manejo de Errores: _________________________________________________________________ 16
Ejemplos de Cursores: _______________________________________________________________ 19
10.- Disparadores ______________________________________________________________ 20
Creación de disparadores. ____________________________________________________________ 21
Eliminación de un disparador. ________________________________________________________ 23
Ejercicios de funciones, procedimientos y disparadores ________________________________ 24
Calcular un NIF ____________________________________________________________________ 24
Validar un NIF _____________________________________________________________________ 24
Validar un e-mail.___________________________________________________________________ 24
Introducir datos en tablas. ___________________________________________________________ 24
Borrado de datos. ___________________________________________________________________ 25
Consulta de datos. __________________________________________________________________ 25

Página 1 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Disparador 1. ______________________________________________________________________ 26
Disparador 2. ______________________________________________________________________ 26

Página 2 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

1.- Vistas y transacciones.


Una vista es una consulta almacenada por el SGBD y que podrá ser posteriormente invocada.

Las vistas pueden ser creadas por usuarios con suficiente privilegio (permiso Create View en
MySQL).

Una vez creada, una vista aparecerá ante nosotros como si se tratase de una tabla.

Para crear una vista recurrimos al comando Create View, cuya sintaxis es:

CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]

Podemos encontrar la sintaxis completa de la instrucción en:


http://dev.mysql.com/doc/refman/5.1/en/create-view.html

Como ejemplo vamos a crear una vista de las actores cuyo nombre comience por la letra a.

CREATE VIEW actor_a


AS
SELECT nombre, apellidos
FROM actores
WHERE nombre LIKE 'a%';

Uno de los parámetros interesantes que no encontramos en otros gestores de bases de datos es el
que indica si vamos a utilizar el nivel de seguridad del creador o del invocador a la hora de permitir
a un usuario acceder a los datos de la vista.

Una transacción es un conjunto de operaciones SQL que debe llevarse a cabo de manera atómica.
Esto significa que todas las operaciones son indivisibles, o se llevan a cabo todas o ninguna debería
de ser válida.

Para definir transacciones de mayoría de SGBD tienen órdenes de inicio de transacción, validación
y anulación.

En el caso de MySQL las ordenes para manejo de transacciones son:

Inicio de transacción: START TRANSACTION


Anulación de transacción: ROLLBACK
Validación de transacción: COMMIT

En MySQL el soporte de transacciones sólo es válido para las tablas tipo InnoDB.

Un ejemplo sería: Una base de datos de un banco. Las tablas Cliente y Moroso tipo innodb.

Página 3 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

START TRANSACTION;
insert into moroso select * from cliente where deuda>0;
delete from cliente where deuda>0;
COMMIT;

Si sucede algún error, por ejemplo hardware, entre las operaciones insert y delete, al reiniciarse
MySQL las transacciones no terminadas será canceladas y las tablas quedarán tal como estaban
antes de iniciarse la transacción. Si no sucede ningún fallo al encontrar COMMIT MySQL validará
la transacción.

A veces, cuando programemos con SQL, seremos nosotros los que anularemos transacciones
mediante la orden ROLLBACK, por ejemplo, tras efectuar alguna comprobación no satisfactoria.

2.- Procedimientos Almacenados.


Los procedimientos almacenados permiten la ejecución de comandos SQL que se agrupan bajo el
nombre común del procedimiento.

Los procedimientos son compilados y almacenados en la base de datos. Una vez creados pueden ser
modificados de nuevo y eliminados. Además de un nombre y una serie de instrucciones SQL
asociadas un procedimiento puede recibir para su funcionamiento una serie de parámetros.

Veamos cual es la sintaxis que debemos seguir para crear un procedimiento:

CREATE [OR REPLACE] PROCEDURE nombreProcedimiento ( [datosparámetro1],


[datosparámetro2],...,[datosparámetron])

INSTRUCCIONES.

Cada uno de los bloques [datosparámetro] obedece a la siguiente sintaxis:

[datosparámetro]:
[IN | OUT | INOUT] nombre_parametro tipo

Es decir, para cada parámetro especificamos si un parámetro introduce datos al procedimiento, los
devuelve o ambas cosas. A continuación se define el nombre del parámetro y, por último, el tipo de
datos asociado.

Veamos algunos ejemplos de creación de procedimientos.


Para ello crearemos una base de datos reducida:

create database videoteca;


USE videoteca;

DROP TABLE IF EXISTS actor;


CREATE TABLE actor (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
nombre VARCHAR(64) NOT NULL,
apellidos VARCHAR(64) NOT NULL,
imdb VARCHAR(32) NOT NULL DEFAULT '',
PRIMARY KEY(id)
);

Página 4 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

E insertaremos en ella algunos valores como ejemplo:

INSERT INTO actor(nombre, apellidos, imdb)


VALUES('Harrison', 'Ford', 'nm0000148');

INSERT INTO actor(nombre, apellidos, imdb)


VALUES('Russell', 'Crowe', 'nm0000128');

Creación de un procedimiento sencillo.


A continuación crearemos un primer procedimiento sencillo que no precise de parámetros al que
llamaremos CONSULTA_ACTOR y que nos servirá para obtener los datos almacenados en la tabla
actor.

CREATE PROCEDURE CONSULTA_ACTOR()


SELECT * FROM actor;

La definición del procedimiento terminará en el momento en que se introduzca “;”.

PROBLEMA: Entonces ¿si cada orden SQL acaba en ; como crear un procedimiento que incluya
más de una orden?. Paciencia, lo veremos enseguida.

Llamada a un procedimiento.

Una vez hemos creado nuestro primer procedimiento sólo nos queda hacerlo funcionar. Para ello
usaremos el comando CALL:

call CONSULTA_ACTOR();

Consultar información sobre los procedimientos creados en la base de


datos.
Para poder saber qué procedimientos se han creado recurrimos al comando show:

show procedure status;

show procedure status\G (para salida de datos formateada).

Consultar código almacenado en un procedimiento.


Para poder ver los detalles de creación de un procedimiento emplearemos el comando show create,
ejemplos:

show create procedure CONSULTA_ACTOR;


o
show create procedure CONSULTA_ACTOR\G (para salida de datos formateada).

Eliminación de un procedimiento.
Para poder eliminar un procedimiento previamente creado emplearemos la orden drop, tal y como
vemos a continuación:

drop procedure CONSULTA_ACTOR;

Página 5 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

3.- Uso de variables.


Los datos no son etéreos y en ocasiones será necesario almacenarlos en algún lugar. Una variable es
ese lugar. En ellas se guardaran los valores que debamos consultar o modificar posteriormente. El
lenguaje SQL es un lenguaje de programación y al igual que todos los lenguajes de programación
admite la definición de variables.

Para definir una variable es necesario seguir la siguiente sintaxis:


DECLARE nombre_variable tipo
[DEFAULT] valor_predeterminado.

Por ejemplo:

DECLARE actores integer default 0;

Asignación de valores a una variable

Existen dos modos de asignar valores a una variable:

Directamente: empleado la palabra reservada SET.

Ejemplo: SET actores=20;

Directamente: empleado el operador de asignación:

Ejemplo: select @usuario:=user();


O
Do @usuario:=user();

Do hace que se asigne el valor a la variable sin producir salida de datos por
pantalla.

Tomando su valor de una consulta: utilizando la palabra clave INTO en una consulta de
selección.

Ejemplo:.........
declare actores integer;
select count(*)into actores
from actor;
............

4.- Delimitadores
Como la experiencia nos demuestra, cada vez que introducimos un “;” en una sentencia SQL
estamos indicando el final de esa sentencia. La sentencia de creación de un procedimiento
almacenado es también SQL y como tal necesita el empleo de dicho delimitador.

Esto nos aboca a un problema en aquellos procedimentos almacenados que precisen de más de una
orden SQL, ¿como diferenciar entre el punto y coma (;) que finaliza una sentencia
perteneciente al cuerpo del procedimiento almacenado y el que marca el final del
procedimiento almacenado?.

Página 6 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Veamos un ejemplo:

create procedure cantidad_actor()


begin
declare actores integer default 0;
select count(*) into actores from actor;
select actores;
end;

La definición del procedimiento anterior presenta las siguientes novedades:

1. Introducimos la aparición de BEGIN ... END como indicadores de comienzo y fin del cuerpo de
un procedimiento. Hasta ahora los procedimientos que habíamos usado como ejemplo no
precisaban recurrir a BEGIN ... END porque sólo constaban de una orden SQL.

2. Utilizamos la definición de una variable a la que asignamos un valor mediante INTO.

3. El valor almacenado en la variable es devuelto por el procedimiento mediante una orden


SELECT sobre la variable.

No obstante, la anterior definición del procedimiento cantidad_actor no funcionará, el problema se


encuentra en el momento en que llegamos a la definición de la variable actores e introducimos el
primer “;”, ya que el interprete de comandos de la base de datos no sabe si al introducirlo le estamos
indicando el final de la definición del procedimiento. Para solucionar este “malentendido sintáctico”
recurrimos al uso de delimitadores mediante la palabra clave DELIMITER. Aunque es posible
emplear casi cualquier carácter como delimitador se recomienda emplear dos caracteres barra
invertida //:

delimiter //
create procedure cantidad_actor()
begin
declare actores integer default 0;
select count(*) into actores from actor;
select actores;
end //
delimiter ;

La explicación al fragmento de código SQL anterior es la siguiente:

1. Antes de comenzar la creación del procedimiento almacenado se declara un nuevo


delimitador.
2. Se crea el procedimiento almacenado y tras la instrucción END se utiliza el delimitador
creado con anterioridad para indicar que se ha terminado de definir el procedimiento.
3. Por último se vuelve a dejar todo “en su sitio” definiendo nuevamente como delimitador el
carácter “;”.

5.- Creación de un procedimiento elaborado con parámetros de


entrada y salida.
Como hemos comentado en secciones anteriores, al definir un procedimiento es posible que dicho
procedimiento reciba parámetros, que pueden ser de entrada y de salida.

Página 7 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

En este apartado vamos a elaborar a modo de ejemplo un procedimiento que recibirá dos
parámetros, uno como entrada a modo de carácter y otro como salida a modo de entero.

La finalidad del procedimiento será presentar por pantalla aquellos actores cuyo nombre sea similar
al primer parámetro recibido y además contar cuantos registros cumplen esta condición. El número
de tales registros se devolverá en la segunda variable, que será de salida.

DELIMITER //
CREATE PROCEDURE busca_actores(
IN letra CHAR(2),
OUT actores INT
)
BEGIN

SELECT * FROM actor


WHERE nombre LIKE letra;

SELECT COUNT(*) INTO actores FROM actor


WHERE nombre LIKE letra;
END //
DELIMITER ;

Un ejemplo de puesta en funcionamiento del procedimiento anterior es el siguiente:


CALL busca_actores('h%', @cantidad);

En el ejemplo anterior nos llama la atención el uso del carácter @ en el segundo parámetro. El
símbolo @ es empleado para crear variables de sesión cuya vida se limita al tiempo que se esté
conectado al sistema. Por tanto, si hemos creado una variable temporal, podemos obtener su valor
tras llamar al procedimiento:

select @cantidad;

Propuesta de actividades

6.- Estructuras de control de flujo


Estructuras condicionales. La estructura IF.
La estructura IF es usada para implementar una estructura condicional básica. Su forma básica es la
siguiente:

IF condicion THEN secuencia_accion1


[ELSEIF condicion2 THEN secuencia_accion2] ...
[ELSE secuencia_accionN]
END IF

Página 8 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Ejemplo:
Delimiter //
Create procedure disponible(out comprueba integer)
Begin
Declare num_actores integer;
Select count(*) into num_actores from actor;
If num_actores<=10 then set comprueba=0;
Else set comprueba=1;
End if
End //
Delimiter ;

Estructuras condicionales. La estructura CASE.


En contrapartida a la composición de estructuras IF … THEN … ELSE … END IF disponemos de
una segunda forma de evaluar múltiples condiciones y de asignar a cada una de ellas una, o un
conjunto, de instrucciones SQL.

Esta segunda forma es mediante la estructura CASE cuya estructura es la siguiente:


CASE case_valor
WHEN condicion THEN secuencia_accion1
[WHEN condicion2 THEN secuencia_accion2 ...
[ELSE secuencia_accionN]
END CASE

Un ejemplo de su aplicación lo podemos obtener remodelando el procedimiento anterior:

Delimiter //
Create procedure disponible(out comprueba integer)
Begin
Declare num_actores integer;
Select count(*) into num_actores from actor;
case num_actores
when <=10 then set comprueba=0;
Else set comprueba=1;
End case
End //
Delimiter ;

7.- Estructuras de repetición.


Todo lenguaje de programación contiene estructuras que permiten la repetición de un fragmento de
código un número definido de veces, o en tanto en cuanto no se de una determinada condición. SQL
no es una excepción.

Veamos cuales son las estructuras de repetición implementadas en SQL.

La estructura LOOP … ITERATE… LEAVE

Esta estructura es equivalente a una estructura GOTO de Basic. Se apoya en la definición de una
etiqueta y en la vuelta a dicha etiqueta mediante las cláusulas Loop o Iterate, o bien la salida de
dicho fragmento mediante la cláusula Leave.

Página 9 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

CREATE PROCEDURE repite(out p1 INTEGER)


BEGIN
etiqueta1: LOOP
SET p1 = p1 + 1;
IF p1 < 10 THEN ITERATE etiqueta1;
END IF;
LEAVE etiqueta1;
END LOOP etiqueta1;
SET @x = p1;
END

En la secuencia de código anterior vemos las siguientes acciones:


1. Observamos que para definir una etiqueta basta especificar su nombre seguido de “:”. En
nuestro caso hemos creado una etiqueta llamada “etiqueta1”.
2. En dicha etiqueta hemos indicado que comenzaba un bucle, ya que la hemos aparejado a una
cláusula LOOP.
3. Este bucle se repite, es de decir ITERA hacía etiqueta1 siempre que el parámetro p1 sea
inferior a 10.
4. Si p1 no es inferior a 10 entonces se produce una cláusula Leave, que indica una ruptura del
control de flujo, es decir, saldrá del bucle definido.
5. Por último todo LOOP lleva aparejado un END LOOP, que se produce al final de todo el
proceso de bucle.

La estructura REPEAT …UNTIL… END REPEAT


Al margen de las estructuras iterativas tipo LOOP … LEAVE …. ITERATE vamos a ver la
existencia de otras dos estructuras que encajan dentro de las estructuras disponibles en los lenguajes
de programación tipo estructurado (recordar que la sentencia GOTO tiene un carácter no
estructurado). La primera de estas constructoras “estructuradas” es REPEAT … UNTIL … END
REPEAT.
La idea de esta constructora es repetir un fragmento de código SQL (aquel que esté comprendido
entre las ordenes REPEAT y END REPEAT, hasta que se de la condición que haga ejecutarse la
orden UNTIL.
La estructura de esta construcción es la siguiente:

[etiqueta_de_inicio:] REPEAT
Lista de instrucciones SQL
UNTIL condición END REPEAT [fin_etiqueta_de_inicio]

Un ejemplo de uso de la constructora

delimiter //

CREATE PROCEDURE repite(p1 INT)


BEGIN
SET @x = 0;
REPEAT
SET @x = @x + 1;
UNTIL @x > p1 END REPEAT;
END//

Página 10 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Delimiter ;

CALL repite(1000);

SELECT @x;

La estructura WHILE…DO… END WHILE

La segunda de las construcciones que nos va a permitir crear bucles es la while…do…end while,
cuya forma de empleo general corresponde a la siguiente construcción:

[etiqueta_de_inicio:] WHILE condicion DO


Lista de Intrucciones SQL
END WHILE [fin_etiqueta_de_inicio]

El funcionamiento de esta estructura, como ya te estarás imaginando, consiste en repetir la


secuencia de comandos SQL indicado como “Lista de Intrucciones SQL” mientras que no se
cumpla la condición que nos permita dar por finalizado el bucle.

Un ejemplo de uso es el siguiente:

CREATE PROCEDURE dowhile()


BEGIN
DECLARE v1 INT DEFAULT 5;

WHILE v1 > 0 DO
...
SET v1 = v1 - 1;
END WHILE;
END

El anterior procedimiento repetiría 5 veces aquellas instrucciones SQL que indicásemos en la línea
con los puntos suspensivos.

Página 11 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

8.- Funciones
Pues estaba claro, en todo lenguaje de programación que se precie no pueden faltar las funciones.
Podemos decir que una función es equivalente a un procedimiento que devuelve un valor.

La forma que debemos seguir para declarar una función es la siguiente:

CREATE FUNCTION nombre ([func_parameter[,...]])


RETURNS TIPO
INSTRUCCIONES

Vemos que la definición de una función es muy similar a la de un procedimiento salvo que
mediante returns especificamos el tipo de dato que la función devuelve.

Creación de funciones.
Veamos algunos ejemplos de funciones:

DELIMITER //
CREATE FUNCTION Hola (s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hola, ',s,'!');
//
DELIMITER ;

La función Hola recibe como parámetro una cadena de 20 caracteres y devuelve una cadena de 50
caracteres, que será el resultado de una concatenación.

Un ejemplo de su uso es:

select hola(‘Mundooo’);

Fijémonos en que para usar una función usamos select en lugar de call.

Veamos un segundo ejemplo de función.

delimiter //
create function cuenta_actores() returns integer
begin
declare cantidad integer default 0;
select count(*) into cantidad from actor;
return cantidad;
end//
delimiter ;

Un ejemplo de su uso es:

select cuenta_actores();

Consultar información sobre las funciones creadas en la base de datos.


Para poder saber qué funciones se han creado recurrimos nuevamente al comando show:

show function status;


o
show function status\G (para salida de datos formateada).

Página 12 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Consultar código almacenado en una función.

Para poder ver los detalles de creación de una función emplearemos el comando show create,
ejemplos:

show create function cuenta_actores;


o
show create function cuenta_actores\G (para salida de datos formateada).

Eliminación de una función.

Para poder eliminar una función previamente creada emplearemos la orden drop, tal y como vemos
a continuación:

drop function CONSULTA_ACTOR;

9.- Cursores
Hasta ahora en todos los procedimientos y funciones hemos usado variables de tipo sencillo
(integer, char, etc) capaces de almacenar en su interior un solo valor. A estos tipos se añade otro
más complejo como el cursor, con el que es posible operar sobre un conjunto de datos en lugar de
con un dato individual.

Una variable de tipo cursor permite recorrer, una a una, las filas de un conjunto de datos,
generalmente en el interior de un bucle while.

Para definir un cursor debemos seguir la siguiente sintaxis:

declare cursor nombre_cursor for select columnas from tabla o vista.

Como vemos las variables de tipo cursor se declaran como otra de tipo cualquiera, sin embargo, es a
la hora de asignar valores donde se encuentra la diferencia, ya que en ellas no almacenamos un
valor concreto sino el puntero de acceso a un grupo de datos que son los devueltos por la cláusula
select de la consulta asociada al cursor.

El resultado de esos datos, el conjunto de filas y columnas devueltos por el SELECT, no se


transfieren instantáneamente, sino que quedan preparados a la espera de que el cursor señale la
recuperación individual de una fila.

Para poder usar un cursor, una vez definido, recurrimos a las siguientes operaciones:

Página 13 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

• Open: la apertura es la primera operación que debe llevarse a cabo después de haberlo
declarado y antes de iniciar la recuperación de los datos. Basta con disponer el nombre del
cursor tras la sentencia OPEN.
• Fetch: esta sentencia se usará para recuperar una fila del conjunto de resultados y pasar a la
siguiente. Su sintaxis es Fetch nombre_cursor into variable1, var 2, ... var N. Las variables
deben seguir el mismo orden de aparición y tipos que los definidos en la declaración del
cursor.
• Close: cierra un cursor previamente abierto.

Veamos un ejemplo de la posible utilidad de los cursores:

delimiter //
create procedure recorre_actor ()
begin
declare cont integer default 1;
declare nom char(64);
declare ap char(64);
declare c cursor for select nombre, apellidos from actor;
open c;
fetch c into nom,ap;
select concat(‘Actor numero ’,cont,’: ’,‘Nombre:’,nom,’ .Apellido:’,ap);
close c;
end//
delimiter ;

call recorre_actor();

El anterior ejemplo nos facilita comprender el uso de un cursor, ahora bien, sólo hemos recorrido el
primer elemento de la lista de valores devueltos en la declaración del cursor. ¿Qué sucede si
queremos recorrer todos los valores?

Respuesta: parece que debemos recurrir a modificar el procedimiento anterior añadiendo una
estructura de repetición, un bucle. Pero .... todo bucle debe detenerse alguna vez, ¿cómo sabemos
que hemos llegado al final de todos los datos y que no podemos seguir haciendo fetch al cursor?.

La respuesta viene de la mano de los manejadores (handlers). Un handler es un mecanismo que


permite capturar un evento determinado (por ejemplo, un error, un fin de cursor, una excepción de
la base de datos) y ejecutar una serie de comandos SQL en respuesta a dicho handler. La definición
de un handler tiene la siguiente forma:

DECLARE handler_tipo HANDLER FOR valor_de_condicion [,...] comandos SQL

El handler_tipo puede asumir uno de los siguientes valores: CONTINUE, EXIT, UNDO.

La declaración del manejador puede cubrir una o más condiciones, que son expresadas separadas
por comas en el apartado valor_de_condicion. Si una de las condiciones indicadas se cumple, la
sentencia SQL especificada en el handler se ejecuta. La sentencia puede ser un comando simple o
un grupo de comandos comprendidos en una sección BEGIN ... END.

Nos queda por ver en qué consiste el handler_tipo:

Página 14 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

CONTINUE: la ejecución de la rutina que originó el motivo del desencadenamiento del handler
continúa después de la ejecución del fragmento de código SQL que dió lugar a la activación del
manejador.

EXIT: la ejecución del fragmento BEGIN ... END dentro de la que se declaró el manejador termina.

UNDO: la operación que desencadenó la llamada al manejador se anula. Esta opción no está
implementada en MySql 5.0.

Cuando ocurre una situación para la que no se ha definido un handler la acción por defecto es
EXIT.

Los valores de condición, en MySql, que se hacen corresponder con el término SQLSTATE,
pueden ser cualquiera de los mostrados en el anexo I Valores de Condición.

Con todo lo anterior, vamos a ver un ejemplo de uso de handler que nos va a servir para poder
recorrer todos los datos de un cursor mediante un bucle. Para ello partiremos del procedimiento
recorre_actor definido anteriormente, al que añadiremos un handler y un bucle:

delimiter //
create procedure recorre_actor ()
begin
declare cont integer default 1;
declare fin integer default 0;
declare nom char(64);
declare ap char(64);
declare c cursor for select nombre, apellidos from actor;
declare continue handler for sqlstate '02000' set fin = 1;
open c;
repeat
if (fin=0) then
fetch c into nom,ap;
select concat(‘Actor numero ’,cont,’: ’,‘Nombre:’,nom,’ .Apellido:’,ap);
set cont=cont+1;
end if;
until fin=1 end repeat;
close c;
end//
delimiter ;

call recorre_actor();

Comentemos brevemente los cambios sufridos por el procedimiento recorre_actor, los cuales hemos
resaltado en negrita.

1. Se ha introducido una nueva variable llamada fin, la cual vale 0 y pasará a valer 1 cuando lo
indique un handler.
2. Se ha definido un handler de tipo CONTINUE que se desencadenará en caso de producirse
la condición SQLSTATE ‘02000’. Esta condición, si la buscamos en el anexo I (valores de
condición) se corresponde con:

Error: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)

Message: No data - zero rows fetched, selected, or processed

Página 15 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

3. Lo anterior quiere decir que ese error se producirá cuando una operación fetch no produzca
datos, bien porque se haya llegado al final de un cursor o porque el cursor esté vacío. En ese
caso hemos especificado que la variable FIN tome el valor 1.
4. Por último, hemos añadido un bucle de tipo repeat until, controlado por la variable FIN, del
que sólo se saldrá cuando dicha variable pase a tomar el valor 1, es decir, una operación
fetch desencadene el handler programado con anterioridad.

Manejo de Errores:

Página 16 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Página 17 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Página 18 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Ejemplos de Cursores:

Página 19 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

10.- Disparadores
Los disparadores, también llamados desencadenadores (triggers en inglés), permiten realizar tareas
de forma automática cuando una determinada circunstancia tiene lugar.

Podemos crear disparadores que se activen antes o después de una inserción, una actualización o un
borrado.

De esta forma se puede comprobar que los valores que se intenta introducir en una determinada
tabla cumplen aquellas condiciones que nos interesan, deteniendo la operación en caso de que se
detecte alguna incongruencia.

También es posible asociar un desencadenador a una operación de actualización de manera que una
modificación de los datos de una determinada tabla active, de forma automática, una actualización
en otra tabla, manteniendo sincronizados los datos que se requieran.

La sintaxis que debemos seguir para crear un disparador es la siguiente:

CREATE TRIGGER nombre momento evento ON tabla FOR EACH ROW instrucciones SQL.

Donde debemos tener en cuenta las siguientes consideraciones:

Página 20 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Nombre: es el nombre que recibirá el disparador. Aquel por el que nos referiremos a él cuando
queramos utilizarlo.

Momento: puede tomar los valores BEFORE (antes) y AFTER (después). Se utiliza para indicar si
las instrucciones asociadas al disparador se ejecutarán antes o después de la operación que lo activó.

Evento: indica el tipo de operación que activará el disparador. Se puede tratar de INSERT,
UPDATE o DELETE.

Tabla: nombre de la tabla con la que estará asociado el disparador.

Instrucciones: utilizaremos BEGIN .. END, al igual que en los procedimientos y funciones, si


deseamos que el disparador tenga más de una instrucción SQL.

Creación de disparadores.
Veamos algunos ejemplos sobre creación de disparadores:

Imaginemos la siguiente tabla que creamos a modo de ejemplo.

Create table persona(


Nombre char(12),
Apellidos char(20));

Vamos a crear un disparador, definido sobre la tabla persona, de forma que cualquier dato que se
inserte en dicha tabla sea transformado automáticamente a caracteres en mayúsculas, para ello nos
ayudaremos de la función UPPER(cadena), ya definida en SQL que devuelve transformada a
mayúsculas una cadena de texto que le haya sido pasada como parámetro.

Comenzamos definiendo el disparador:

Create trigger persona_insert before insert on persona for each row


Begin

End

Con los anteriores comandos estamos efectuando las siguientes consideraciones:

1. Vamos a crear un disparador al que llamaremos persona_insert.


2. El disparador estará asociado a la tabla persona.
3. Se desencadenará cuando se produzca una inserción en dicha tabla.
4. ¿Antes o después de que se produzca la inserción?. En este caso suponemos que
antes ya que no se necesita esperar que los valores sean insertados.

Teniendo claro esta serie de puntos introduzcamos un nuevo dato importante. ¿Cómo sabe el
disparador los valores que se están tratando de modificar en la tabla?.

Para responder a esta pregunta entrar en juego los operadores NEW y OLD de la siguiente forma:

NEW  Para inserciones y actualizaciones. La forma de uso es NEW.nombre_atributo de forma


que, por ejemplo NEW.nombre sería el nombre que se va a introducir o actualizar o que se acaba de
introducir o actualizar (dependiendo de si el momento es Before o After).

Página 21 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

OLD  Para borrados. La forma de uso es OLD.nombre_atributo de forma que, por ejemplo
OLD.nombre sería el nombre que se va a eliminar o que se acaba de eliminar (dependiendo de si el
momento es Before o After).

Delimiter //
Create trigger persona_insert before insert on persona for each row
Begin
Set New.nombre=upper(new.nombre);
Set New.apellidos=upper(new.apellidos);
End//
Delimiter ;

Probamos a continuación el uso del disparador.

Insert into persona (nombre, apellidos) values (‘antonio’,’lopez cano’);


Insert into persona (nombre, apellidos) values (‘miguel’,’perez garcia’);

Select * from persona;

Si todo ha funcionado correctamente, el disparador habrá transformado de forma transparente los


nombres y apellidos a mayúsculas.

Un segundo ejemplo, imaginemos que deseamos añadir a la tabla persona un nuevo campo llamado
abreviatura que se actualice automáticamente y cuyo valor sean las tres primeras letras del apellido
y las dos primeras letras del nombre en ese orden.

Los pasos que podríamos seguir son los siguientes:

Alter table persona


Add abreviatura char(5);
Delimiter //
Create trigger act_abrev before update on persona for each row
Begin
Declare av1 char(3);
Declare av2 char(2);
Declare av3 char(5);
Set av1=left(new.apellidos,3);
Set av2=left(new.nombre,2);
Set av3=concat(av1,av2);
set new.abreviatura=av3;
End//
Delimiter ;

Comprobamos la tabla persona:

Select * from persona;

Forzamos la actualización de los registros existentes de forma que mantengan el mismo valor pero
salte el disparador:

Update persona set nombre=nombre


Select * from persona;

Página 22 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Insertamos un nuevo dato en la tabla:


Insert into persona (nombre, apellidos) values (‘Marcos’,’Gutierrez’);
Select * from persona;

¿Se han actualizado los datos de la nueva inserción?. Evidentemente no, el disparador que hemos
programado está definido para funcionar tras una actualización. Si queremos que comience a
funcionar antes de una inserción deberemos crear un disparador tipo before insert, simplemente
transformando el disparador anterior en uno nuevo.

Ahora bien, existe un problema y es que ya tenemos definido un disparador para el evento before
insert sobre la tabla persona, por lo que deberíamos remodelarlo:
Drop trigger persona_insert;
Delimiter //
Create trigger persona_insert before insert on persona for each row
Begin
Set New.nombre=upper(new.nombre);
Set New.apellidos=upper(new.apellidos);
Set new.abreviatura=concat(left(new.apellidos,3),left(new.nombre,2));
End//
Delimiter ;

Actualizamos y comprobamos:
Update persona set nombre=nombre
Select * from persona;

Insertamos y comprobamos:
Insert into persona (nombre, apellidos) values (‘Rosa’,’Garcia’);
Select * from persona;

En la actualización ha entrado en juego el disparador act_abrev, mientras que en la inserción el


disparador que ha “saltado” ha sido la nueva versión de persona_insert.

Evidentemente una vez que hemos actualizado los datos de la tabla podemos prescindir de
act_abrev y dejar en funcionamiento persona_insert. Para ello lo eliminaremos.

Eliminación de un disparador.
Para poder eliminar un disparador emplearemos la orden drop, tal y como vemos a continuación:
drop trigger act_abrev;

Propuestas de actividades con disparadores:

Página 23 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Ejercicios de funciones, procedimientos y disparadores

Calcular un NIF

Crear una función llamada letranif que calcule y devuelva la letra del nif de un DNI, que recibirá a
modo de parámetro, como número entero.

Calcular la letra del NIF, es sencillo siguiendo los siguientes pasos:


1.- Dividir por 23 el DNI y prescindir de los decimales.
2.- Multiplicar ese numero por 23 y restarlo del DNI.
3.- Te saldrá un número del 0 al 23, entonces solo tienes que aplicar la siguiente tabla:
1R 2W 3A 4G 5M 6Y 7F 8P 9D 10X 11B 12N 13J 14Z 15S 16Q 17V 18H 19L 20C 21K 22E 23T
0T

Ejemplo dni nº: 22187230


dni nº: 22187230 / 23 = 964662,17391304347826086956521739
Nos quedamos la parte entera: 964662 y multiplicamos por 23: 22187226
Restamos: 22187230 – 22187226 = 4.
Letra que corresponde al nº4: G.

Para desarrollar el ejercicio se recomienda utilizar las funciones para manipulación de cadenas de
texto que sean necesarias (consultar manual de referencia de MySql que se adjunta).

Validar un NIF
Crear una función llamada validanif que devuelva el valor 1 si el nif que ha recibido como
parámetro de tipo char(10) es válido, si el NIF recibido no es válido devolverá el valor 0.

Para desarrollar el ejercicio se recomienda utilizar las funciones para manipulación de cadenas de
texto que sean necesarias (consultar manual de referencia de MySql que se adjunta).

Validar un e-mail.

En este ejercicio vamos a crear la función emailok, que recibe como parámetro una cadena de texto
de 30 caracteres y devuelve el valor 1 si la cadena recibida corresponde a una dirección de correo
electrónico y 0 en caso contrario.

Consideramos que una dirección de correo es valida si al menos cumple que existan dos caracteres
iniciales, tras los cuales exista una arroba, a continuación al menos dos caracteres y por último un .
tras el cual al menos deben existir dos caracteres mas.

Para desarrollar el ejercicio se recomienda utilizar las funciones para manipulación de cadenas de
texto que sean necesarias (consultar manual de referencia de MySql que se adjunta).

Introducir datos en tablas.

Página 24 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

El siguiente cometido que vamos a afrontar va a ser crear un procedimiento que nos sirva para
introducir cómodamente datos en una tabla. Para ello, en primer lugar vamos a crear la tabla
SOLTERO con los siguientes campos:

NIF : char de longitud 10. Clave primaria.


Nombre: char 15.
Apellidos: char 30.
Telefono: char 9.
email: char 30.

Y la tabla CASADO con idénticos campos.

A partir de lo anterior crearemos el procedimiento insert_soltero, para insertar datos en la tabla


SOLTEROS. Dicho procedimiento tendrá los siguientes parámetros:

1º -> Dni. Entero.


2º -> Nombre: char 15.
3º -> Apellidos: char 30.
4º -> Telefono: char 9.
5º -> email: char 30.

El procedimiento deberá, a partir del Dni recibido y, apoyándose en la función LETRANIF creada
con anterioridad, calcular el NIF completo que será el valor que almacenará en la tabla.

En el caso del e-mail el procedimiento se apoyará en la función emailok de forma que si el email
recibido no es válido no deberá almacenarse sino que para esa persona el campo e-mail asumirá el
valor NULL.

Crearemos también el procedimiento insert_casado para insertar datos en la tabla CASADOS con
idénticas condiciones al procedimiento anterior.

Borrado de datos.
El siguiente ejercicio que vamos a desarrollar consistirá en crear los procedimientos que nos sirvan
para eliminar cómodamente datos de las tablas SOLTEROS y CASADOS.

Los procedimientos a crear serán Borra_Soltero y Borra_Casado, el usuario sólo indicará el DNI de
la persona a eliminar y los procedimientos se encargarán de calcular el NIF correspondiente a ficho
DNI y eliminarlo de la tabla. Si el DNI indicado no tiene equivalente NIF asociado significará que
dicha persona no existe en la tabla y el procedimiento deberá hacer que aparezca el mensaje “DNI:
nº_del_dni DESCONOCIDO. NO SE HAN BORRADO DATOS”.

Consulta de datos.
Crear un procedimiento llamado consulta_nombres que obtenga sólo aquellos solteros o casados
cuyo nombre sea similar a un párametro de tipo char pasado al procedimiento. La salida de datos
debe ser similar a “Casados como se llaman como VVVVVVV”, apareciendo a continuación los
datos de los casados que cumplen con el criterio y a continuación “Solteros que se llaman como
VVVVVVV” seguido de los correspondientes datos. Si en alguno de los dos casos no existen datos
que cumplan con el criterio en el correspondiente apartado deberá aparecer el mensaje “No existen
casados que cumplan el criterio” o “No existen casados que cumplan el criterio”, según el caso.

Página 25 de 26
ASGBD. Unidad 4. Automatización de tareas. Scripts.

Disparador 1.

Crear un disparador llamado check_casados, asociado a la tabla de casados de forma que al


introducir una persona casada en dicha tabla, si la misma persona existe en la tabla de solteros la
elimine de solteros.

Disparador 2.

Crear una tabla llamada Bajas con idénticos campos que las tablas solteros y casados junto con un
campo adicional llamado Estado que será un char (1) con valor C si la persona que estamos dando
de baja estaba casada y S si estaba soltera.

Una vez creada la tabla Bajas crear sendos disparadores a las tablas casados y solteros de forma que
ante una eliminación en las tablas casados y solteros los datos de la persona eliminada sean
anexados a la tabla bajas junto con su estado (C o S).

Página 26 de 26

También podría gustarte