mysql procedural sql - puro
TRANSCRIPT
-
8/19/2019 Mysql Procedural SQL - Puro
1/25
-
8/19/2019 Mysql Procedural SQL - Puro
2/25
Parámetros de Entrada y Salida en un Procedimiento
Un parámetro es un dato necesario para el funcionamiento del procedimiento, ya que
contribuyen al correcto desarrollo de las instrucciones del bloque de instrucciones.
Los parámetros pueden ser de entrada (IN), salida (OUT) o entrada/salida (INOUT) y deben
tener definido un tipo. Un parámetro de entrada en un dato que debe ser introducido en la
llamada del procedimiento para definir alguna acción del bloque de instrucciones.
Un parámetro de salida es un espacio de memoria en el cual el procedimiento devolverá
almacenado su resultado. Y un parámetro de entrada/salida contribuye tanto como a ingresar
información útil como para almacenar los resultados del procedimiento. Por defecto, si no
indicas el tipo de parámetro MySQL asigna IN.
Para especificar el tipo de parámetro seguimos la siguiente sintaxis:
[{IN|OUT|INOUT} ] nombre TipoDeDato
Atributos de un Procedimiento en MySQL Son características adicionales para establecer la naturaleza del procedimiento. Veamos la
utilidad de algunas:
LANGUAGE SQL: Indica que el procedimiento se escribirá en lenguaje estándar SQL/PSM.
Pero su utilidad se basa en la suposición de que en el futuro los procedimientos podrían ser
escritos en otros lenguajes como Php, Java, etc. Ya que aun los escribimos en SQL entonces
no es necesario ponerlo.
SQL SECURITY {DEFINER|INVOKER}: Establece el nivel de seguridad de invocación de un
procedimiento. Si usas DEFINER el procedimiento sera ejecutado con los permisos del usuario
que lo creó, y si usas INVOKER será ejecutado con los permisos del usuario que lo esta
invocando.
[NOT] DETERMINISTIC: Especifica si el procedimiento devolverá siempre el mismo resultado
al ingresar los mismo parámetros. O si devolverá distintos resultados al ingresar los mismo
resultados. Un ejemplo sería ingresar la suma 1+2, se sabe que siempre el resultado será 3,así que usamos DETERMINISTIC. Pero si el parámetro es un valor de un retiro de cuenta
bancaria, el resultado del saldo que queda será diferente sin importar la cantidad retirada.
NO SQL|CONTAINS SQL|READS SQL DATA|MODIFIES SQL DATA: Estas características
determinan la estructura del procedimiento. NO SQL indica que el procedimiento no contiene
sentencias del lenguaje SQL. READS SQL DATA especifica que el procedimiento lee
http://www.hermosaprogramacion.com/2014/05/sql.htmlhttp://www.hermosaprogramacion.com/2014/05/sql.htmlhttp://www.hermosaprogramacion.com/2014/05/sql.htmlhttp://www.hermosaprogramacion.com/2014/05/sql.html
-
8/19/2019 Mysql Procedural SQL - Puro
3/25
información de la base de datos mas no escribe datos. MODIFIES SQL DATA indica que el
procedimiento escribe datos en la base de datos. CONTAINS SQL es el tipo por defecto de un
procedimiento e indica que el procedimiento contiene sentencias SQL
COMMENT cadena: Con este atributo podemos añadir una descripción al procedimiento con
respecto a las instrucciones que ejecuta. Por ejemplo,“Este procedimiento da de baja a todoslos cli entes que hace 3 meses no compran a la compañía” .
Ejemplo de un Procedimiento con un parámetro IN
En el siguiente ejemplo desarrollemos un procedimiento para el siguiente requerimiento:
Imprima los números del 1 hasta n, donde n esta dado por el usuario.
Usaremos un procedimiento para capturar el numero n del usuario. Incorporaremos una
variable contadora que comience en 1 y un WHILE para el incremento e impresión. Veamos:
DELIMITER //
CREATE PROCEDURE numeros_1_hasta_n (IN n INT)
BEGIN
DECLARE contador INT DEFAULT 1;
WHILE contador
-
8/19/2019 Mysql Procedural SQL - Puro
4/25
Modificar un Procedimientos en MySQL
Para modificar un procedimiento en MySQL usaremos la sentencia ALTER PROCEDURE. Esta
modificación permite cambiar el nivel de seguridad y la descripción del procedimiento.
ALTER PROCEDURE nombre
[SQL SECURITY {DEFINER |INVOKER }]
[COMMENT descripción]
Ejemplo: Cambiar la descripción de un Procedimiento A continuación mostraremos un procedimiento que inserta un cliente en la base de datos.
DELIMITER //
CREATE PROCEDURE insertar (id_cliente INT, nombre_cliente VARCHAR (100), apellido_cliente
VARCHAR (100))
COMMENT 'Procedimiento que inserta un cliente a la base de datos'
BEGIN
IF NOT EXISTS ( SELECT C.ID
FROM CLIENTE AS C
WHERE C.ID = id_cliente) THEN
INSERT INTO CLIENTE(ID, NOMBRE, APELLIDO)
VALUES ( id_cliente,nombre_cliente,apellido_cliente);
ELSE
SELECT 'Este cliente ya existe en la base de datos!';
END IF;
http://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/2014/05/bases-de-datos.html
-
8/19/2019 Mysql Procedural SQL - Puro
5/25
END//
DELIMITER ;
Ahora le cambiaremos la descripción mediante ALTER PROCEDURE:
ALTER PROCEDURE insertar_cliente
COMMENT 'Insertar Cliente'
Borrar un Procedimiento en MySQL La sentencia DROP permite borrar un procedimiento de MySQL. Obviamente el
procedimiento debe estar almacenado con anterioridad para poder llevar a cabo la operación.
Dado el caso de que no se encuentre creado, podemos usar el operador EXISTS junto al
condicional IF para comprobar su existencia.
DROP PROCEDURE [IF EXISTS] nombre_procedimiento
Ejemplo: Eliminar un Procedimiento antes de crearlo La eliminación de un procedimiento se lleva a cabo con DROP PROCEDURE. Es común usa esta
sentencia antes de crear un procedimiento.
Como ejemplo crearemos un procedimiento llamado mostrar_clientes, el cual
simplemente consulta todas las columnas de una tabla llamada CLIENTE:
DROP PROCEDURE IF EXISTS mostrar_clientes;
CREATE PROCEDURE mostrar_clientes()
SELECT * FROM CLIENTE;
Si el procedimiento que deseamos crear ya existe, entonces lo borraremos para darle paso a
la nueva definición.
Mostrar un Procedimiento en MySQL
Para mostrar las características de un procedimiento en MySQL usaremos la
sentencia SHOW CREATE PROCEDURE.
SHOW CREATE PROCEDURE nombre_procedimiento
http://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-exists.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-exists.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-if-else.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-if-else.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-if-else.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-if-else.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-exists.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.html
-
8/19/2019 Mysql Procedural SQL - Puro
6/25
Podrías mostrar un ejemplo? Por supuesto!, a continuación mostraremos las características de
un procedimiento llamadoHELLOWORLD que se encuentra gestionado
por phpMyAdmin de XAMPP.
-
8/19/2019 Mysql Procedural SQL - Puro
7/25
Creación de Cursores en MySQL junio 17, 2014 James Revelo
Un cursor es un objeto que apunta a las filas retornadas de una consulta. Esta característica
permite manipular los datos de cada fila de forma individual. MySQL usa la palabra
reservada CURSOR para declarar estos espacios de lectura.
¿Qué son los Cursores en MySQL?
Recuerda que cuando consultábamos tablas con SELECT, MySQL arrojaba rápidamente
los registros en pantalla de un solo tiro y nosotros eramos felices. Pero hay momentos donde
necesitarémos acceder a cada registro de forma individual.
Lo que quiere decir que un cursor permite acceder en tiempo real a los datos de cada fila de
una consulta. Este mecanismo es de gran utilidad cuando vayamos a comunicar MySQL con
aplicativos o realizar consultas complejas.
¿Como usar Cursores en MySQL?
Para implementar un cursor debemos tener en cuenta 4 fases de su funcionamiento:
Declaración
Apertura
Lectura
Cierre
1. DECLARACION
Al igual que una una variable, los cursores se declaran con la sentencia DECLARE.
Debemos declararlos después de nuestras variables corrientes, de lo contrario MySQL,
generará un error. Veamos la sintaxis:
http://www.hermosaprogramacion.com/2014/06/mysql-cursores/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/05/SELECT-SQL.htmlhttp://www.hermosaprogramacion.com/2014/05/SELECT-SQL.htmlhttp://www.hermosaprogramacion.com/2014/05/SELECT-SQL.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-variables.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-variables.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-cursores.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-sql-server-variables.htmlhttp://www.hermosaprogramacion.com/2014/05/SELECT-SQL.htmlhttp://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/06/mysql-cursores/
-
8/19/2019 Mysql Procedural SQL - Puro
8/25
DECLARE nombre_cursor CURSOR FOR ;
Este sería un ejemplo:
DECLARE cursor_edad CURSOR FOR
SELECT EDAD FROM CLIENTE
WHERE NOMBRE LIKE 'a%';
No significa que el objeto cursor_edad vaya a guardar los datos de la consulta a la cual esta
referenciando. Lo que hace es apuntar a la dirección de memoria del primer resultado de
dicha consulta. Si tienes conocimientos en C++ se te hará mas fácil comprender esta
interpretación.
2. APERTURA
En la fase de declaración la consulta a la que hace referencia el cursor, aun no se ha ejecutado.
Para ejecutarla usaremos el comando OPEN. Sin esta apertura los resultados del cursor no
pueden ser leídos por MySQL, por lo tanto se producirá un error.
Debes tener en cuenta que al abrir el cursor este sitúa un puntero a la primera fila arrojada
por la consulta.
OPEN nombre_cursor ;
3. LECTURA
La lectura de los resultados de un cursor se hace con el comando FETCH. Este nos permite
acceder a la primer fila generada por la consulta. Si se vuelve a usar el cursor pasa a apuntar
a la segunda fila, luego a la tercer y así sucesivamente hasta que el cursor no tenga resultados
que referenciar.
FETCH nombre_cursor INTO variable1,variable2,...
Es importante tener variables declaradas para almacenar temporalmente los datos de las
columnas de cada fila, generadas por la consulta. Estas variables lógicamente deben tener el
mismo tipo de dato que el valor de la columna a almacenar, y luego relacionarlas con la
sentencia INTO.
http://cprogramacionc.blogspot.com/http://cprogramacionc.blogspot.com/http://www.hermosaprogramacion.com/2014/05/tipos-datos-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/tipos-datos-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/tipos-datos-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/tipos-datos-sql.htmlhttp://cprogramacionc.blogspot.com/
-
8/19/2019 Mysql Procedural SQL - Puro
9/25
Por ejemplo, si quisiéramos almacenar el id , nombre y apellido del primer empleado de la
tabla EMPLEADO, hacemos lo siguiente:
-- Declaración de variables para el cursor
DECLARE ID INT;
DECLARE NOMBRE VARCHAR (100);
DECLARE APELLIDO VARCHAR (100);
DECLARE cursor_cliente CURSOR
FOR SELECT ID, NOMBRE, APELLIDO FROM CLIENTE;
OPEN cursor_cliente;
FETCH cursor_cliente INTO ID, NOMBRE,APELLIDO;
CLOSE cursor_cliente;
Me imagino que intuyes que si queremos recorrer todas las filas de la consulta, necesitaremos
de alguna estructura repetitiva, ¿no es cierto?, claro!, incluir el comando FETCH dentro
de un bucle permite leer todos los resultados de un cursor. Cuando el cursor llegue al final
de los resultados de la consulta, entonces el bucle termina. Pero terminar un bucle de este
tipo necesita una condición de parada especial en MySQL.
Existen manejadores de errores en MySQL para esta tarea, aunque por el momento no los
hemos estudiado es necesario saber lo siguiente:
Cuando usamos FETCH en el cursor, pero ya no hay mas filas por retornar, MySQL arroja
un error llamado “02000 NO DATA FECH”. Así que lo que debemos hacer es crear
un manejador para indicar que cuando suceda ese error, el programa no termine, pero que
si termine el bucle. Veamos:
-- Declaración de un manejador de error tipo NOT FOUND
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @hecho = TRUE;
Aquí indicamos que si ocurre un error tipoNOT FOUND, entonces asignemos a la variable
@hecho el valor de TRUE. Con esa variable podremos manejar la terminación de nuestro
bucle mas adelante.
4. CIERRE
Una vez leído todos los resultados del cursor, procedemos a cerrar y limpiar espacios de
memoria con CLOSE.
-
8/19/2019 Mysql Procedural SQL - Puro
10/25
CLOSE nombre_cursor ;
Ejemplo de un Procedimiento con un Cursor El siguiente es un ejemplo construido con fines educativos:
Cree un procedimiento en MySQL que imprima el código y el total acumulado de ventas del
vendedor que mas facturó. Tenga en cuenta que el procedimiento debe recibir la fecha inicial
y la fecha final, para estimar el lapso de tiempo en el que se calculará el acumulado.
El anterior requerimiento se crea a partir de una minibase de datos para un sistema de
facturación que tiene el siguiente diagrama entidad-relación:
Diagrama entidad relación de un sistema de facturación.
Diseñador de phpMyAdmin
Antes de desarrollar el procedimiento, especificaremos el flujo en las entradas, procesos y
salidas del programa:
Entradas
Las variables fecha_inicio y fecha_final
Procesos
Consultar las facturas que liquidó el vendedor en las fechas estipuladas como entrada.
Encontrar los detalles de cada factura asociada al vendedor.
http://www.hermosaprogramacion.com/wp-content/uploads/2014/06/MySQL-CURSOR-sistema-comercial.png
-
8/19/2019 Mysql Procedural SQL - Puro
11/25
Multiplicar el precio por la cantidad de cada detalle y guardarlo en la variable
acumulado_ventas.
Comparar el acumulado_ventas de cada vendedor mediante un bucle, para obtener el mejor
vendedor.
Salida
Mostrar en la pantalla el código y la variable acumulado_ventas del mejor vendedor.
Una vez comprendido estos pasos, solo queda implementar el código. Veamos:
DELIMITER //
CREATE PROCEDURE mejor_vendedor (fecha_inicio DATE, fecha_final DATE)
BEGIN
-- Declaración de variables
DECLARE ID_VENDEDOR INT;
DECLARE ACUMULADO_VENTAS INT;
DECLARE TEMPV INT DEFAULT 0;
DECLARE TEMPID INT DEFAULT 0;
-- Definición de la consulta
DECLARE mejor_vendedor_cursor CURSOR FOR
SELECT V.IDVENDEDOR ,SUM(DF.UNIDADES*DF.PRECIO)
FROM VENDEDOR AS V INNER JOIN FACTURA AS F
ON V.IDVENDEDOR = F.IDVENDEDOR AND (F.FECHA BETWEEN fecha_inicio AND fecha_final)
INNER JOIN DETALLEFACTURA AS DF
ON F.IDFACTURA = DF.IDFACTURA
GROUP BY V.IDVENDEDOR ;
-- Declaración de un manejador de error tipo NOT FOUND
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @hecho = TRUE;
-- Abrimos el cursor
OPEN mejor_vendedor_cursor ;
-
8/19/2019 Mysql Procedural SQL - Puro
12/25
-- Comenzamos nuestro bucle de lectura
loop1: LOOP
-- Obtenemos la primera fila en la variables correspondientes
FETCH mejor_vendedor_cursor INTO ID_VENDEDOR , ACUMULADO_VENTAS;
-- Si el cursor se quedó sin elementos,
-- entonces nos salimos del bucle
IF @hecho THEN
LEAVE loop1;
END IF;
-- Guardamos el acumulado de ventas y el código
-- si el vendedor actual tiene mejores resultados
IF ACUMULADO_VENTAS>=TEMPV THEN
SET TEMPV = ACUMULADO_VENTAS;
SET TEMPID = ID_VENDEDOR ;
END IF;
END LOOP loop1;
-- Cerramos el cursor
CLOSE mejor_vendedor_cursor ;
-- Imprimimos el código y total acumulado de ventas del vendedor
SELECT TEMPID AS CODIGO_VENDEDOR , TEMPV AS TOTAL_VENTAS;
END//
DELIMITER ;
MySQL no permite que los cursores lean los resultados de una consulta desde el ultimo
elemento hasta el primero. Usa ORDER BY para organizar tu mismo la información.
MySQL no permite que saltemos a una fila en particular para ahorrarnos tiempo, debemos
recorrer obligatoriamente uno a uno los resultados.
http://www.hermosaprogramacion.com/2014/05/sql-order-by.htmlhttp://www.hermosaprogramacion.com/2014/05/sql-order-by.htmlhttp://www.hermosaprogramacion.com/2014/05/sql-order-by.html
-
8/19/2019 Mysql Procedural SQL - Puro
13/25
-
8/19/2019 Mysql Procedural SQL - Puro
14/25
Crear Funciones En MySQL junio 20, 2014 James Revelo
Una función en MySQL es
una rutina creada para tomar unos parámetros, procesarlos y retornar en un salida.
Se diferencian de los procedimientos en las siguientes características:
Solamente pueden tener parámetros de entrada IN y no parámetros de salida OUT o INOUT
Deben retornar en un valor con algún tipo de dato definido
Pueden usarse en el contexto de una sentencia SQL
Solo retornan un valor individual, no un conjunto de registros.
Como creo una función?Debes usar la sentencia CREATE FUNCTION. La sintaxis para crear una función es casi idéntica
a la de crear un procedimiento, veamos:
CREATE FUNCTION nombre_función ( parametro1, parametro2,...)
RETURNS tipoDato
[atributos de la rutina]
La única diferencia entre la creación de un procedimiento y una función es que la sintaxis de una
función contiene la palabra reservada RETURNS para indicar que tipo de dato se retornará.
Podemos ver un ejemplo?
Claro! Fíjate como obtenemos el factorial de un numero x ingresado como parámetro:
http://www.hermosaprogramacion.com/2014/06/mysql-function/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/05/tipos-datos-sq/http://www.hermosaprogramacion.com/2014/05/tipos-datos-sq/http://www.hermosaprogramacion.com/2014/05/tipos-datos-sq/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/2014/05/tipos-datos-sq/http://www.hermosaprogramacion.com/2014/06/mysql-procedure/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/06/mysql-function/
-
8/19/2019 Mysql Procedural SQL - Puro
15/25
DELIMITER //
CREATE FUNCTION factorial(x INT) RETURNS INT(11)
BEGIN
DECLARE factorial INT;
-- Guardamos el valor de x
SET factorial = x ;
-- Caso en que x sea menor o igual a 0
IF x
-
8/19/2019 Mysql Procedural SQL - Puro
16/25
END//
DELIMITER ;
No confundas RETURNS con RETURN. La primera es para indicar el tipo de dato de retorno
de la función y la segunda es para retornar el valor en el cuerpo de la función.
Puedes mostrar como usar una función en un SELECT?
A continuación crearemos un función que retorne en el nombre completo de la prioridad de un cliente,
introduciendo como parámetro el campo prioridad.
Creación de la función:
DELIMITER //
CREATE FUNCTION EXT_PRIORIDAD (cliente_prioridad VARCHAR (5)) RETURNS VARCHAR (20)
BEGIN
CASE cliente_prioridad
WHEN 'A' THEN
RETURN 'Alto';
WHEN 'M' THEN
RETURN 'Medio';
WHEN 'B' THEN
RETURN 'Bajo';
ELSE
RETURN 'NN';
END CASE;
END//
DELIMITER ;
Con ella podremos consultar de la siguiente forma a los clientes de la base de datos:
-
8/19/2019 Mysql Procedural SQL - Puro
17/25
SELECT NOMBRE, APELLIDO, EXT_PRIORIDAD(PRIORIDAD)
FROM CLIENTE;
De esta manera hemos usado nuestra función en un contexto de consulta. También podemos
usar funciones en las sentencias DELETE y UPDATE, siempre y cuando el valor retornado
sea acorde con las necesidades.
Como actualizar una función?
Para actualizar una función usamos el comando ALTER FUNCTION. Con esta sentencia podemos
cambiar los atributos de la función, pero no podremos cambiar el cuerpo. Veamos la sintaxis:
ALTER FUNCTION nombre_funcion
[SQL SECURITY {DEFINER |INVOKER }]
[COMMENT descripción ]
Si quisiéramos añadir una descripción a una función que calcula el promedio de huéspedes diario con
respecto a una fecha llamada promedio_huespedes, hacemos lo siguiente:
ALTER FUNCTION promedio_huespedes
COMMENT 'Calculo del promedio diario de huéspedes entre una fecha inicial y una fecha final';
Como borrar una función?
Usando el comando DROP FUNCTION. Simplemente especificamos el nombre de la función y esta
se borrará de la base de datos. Su sintaxis esta definida de la siguiente forma:
DROP FUNCTION nombre_funcion
Por ejemplo, para borrar una función que retorna en el ingreso neto con respecto a todos los tiquetes
aéreos comprados en una sucursal de una aerolínea, llamada ingreso_neto_sucursal:
DROP FUNCTION ingreso_neto_sucursal;
http://www.hermosaprogramacion.com/2014/05/bases-de-datos/http://www.hermosaprogramacion.com/2014/05/bases-de-datos/http://www.hermosaprogramacion.com/2014/05/bases-de-datos/http://www.hermosaprogramacion.com/2014/05/bases-de-datos/
-
8/19/2019 Mysql Procedural SQL - Puro
18/25
Crear Triggers en MySQL junio 28, 2014 James Revelo
Un Trigger en MySQL es un programa almacenado(stored program ), creado para
ejecutarse automaticamente cuando ocurra un evento en nuestra base de datos. Dichoseventos son generados por los comandos INSERT, UPDATE y DELETE, los cuales hacen
parte del DML(Data Modeling Languaje) de SQL.
Esto significa que invocaremos nuestros Triggers para ejecutar un bloque de
instrucciones que proteja, restrinja o preparen la información de nuestras tablas, al momento
de manipular nuestra información. Para crear triggers en MySQL necesitas los privilegios
SUPER Y TRIGGER.
Crear un Trigger en MySQL
Aprovecha el Viernes negro en Udemy, cursos de programación a $10
Usaremos una sintaxis similar a la creación de Procedimientos y Funciones en MySQL.
Observemos:
CREATE [DEFINER ={usuario|CURRENT_USER }]
TRIGGER nombre_del_trigger {BEFORE|AFTER } {UPDATE|INSERT|DELETE}
ON nombre_de_la_tabla
FOR EACH ROW
Obviamente la sentencia CREATE es conocidisima para crear nuevos objetos en la base de
datos. Eso ya lo tienes claro. Enfoquemos nuestra atención en las otras partes de la definición:
DEFINER={usuario|CURRENT_USER}
: Indica al gestor de bases de datos qué usuario tiene privilegios en su cuenta, para lainvocación de los triggers cuando surjan los eventos DML. Por defecto este característica
tiene el valor CURRENT_USER que hace referencia al usuario actual que esta creando el
Trigger.
nombre_del_trigger:
Indica el nombre de nuestro trigger. Existe una nomenclatura muy práctica para nombrar
http://www.hermosaprogramacion.com/2014/06/mysql-trigger/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/2014/05/insert-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/insert-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/insert-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/update-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/update-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/update-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/delete-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/delete-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/delete-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/sql.html#concepto-DMLhttp://www.hermosaprogramacion.com/2014/05/sql.html#concepto-DMLhttp://www.hermosaprogramacion.com/2014/05/sql.html#concepto-DMLhttp://www.hermosaprogramacion.com/2014/06/sql-server-mysql-bloque-instrucciones.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-server-mysql-bloque-instrucciones.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-server-mysql-bloque-instrucciones.htmlhttp://click.linksynergy.com/fs-bin/click?id=QuT3oxcXTHw&offerid=323058.302&type=4&subid=0http://click.linksynergy.com/fs-bin/click?id=QuT3oxcXTHw&offerid=323058.302&type=4&subid=0http://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-function.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-function.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-function.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-function.htmlhttp://www.hermosaprogramacion.com/2014/06/mysql-procedure.htmlhttp://click.linksynergy.com/fs-bin/click?id=QuT3oxcXTHw&offerid=323058.302&type=4&subid=0http://click.linksynergy.com/fs-bin/click?id=QuT3oxcXTHw&offerid=323058.302&type=4&subid=0http://www.hermosaprogramacion.com/2014/06/sql-server-mysql-bloque-instrucciones.htmlhttp://www.hermosaprogramacion.com/2014/06/sql-server-mysql-bloque-instrucciones.htmlhttp://www.hermosaprogramacion.com/2014/05/sql.html#concepto-DMLhttp://www.hermosaprogramacion.com/2014/05/delete-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/update-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/insert-sql.htmlhttp://www.hermosaprogramacion.com/2014/05/bases-de-datos.htmlhttp://www.hermosaprogramacion.com/author/admin/http://www.hermosaprogramacion.com/2014/06/mysql-trigger/
-
8/19/2019 Mysql Procedural SQL - Puro
19/25
un trigger, la cual nos da mejor legibilidad en la administracion de la base de datos. Primero
ponemos el nombre de tabla, luego especificamos con la inicial de la operación DML y
seguido usamos la inicial del momento de ejecución(AFTER o BEFORE). Por ejemplo:
-- BEFORE INSERT
clientes_BI_TRIGGER
BEFORE|AFTER: Especifica si el Trigger se ejecuta antes o después del evento DML.
UPDATE|INSERT|DELETE:
Aquí eliges que sentencia usarás para que se ejecute el Trigger.
ON nombre_de_la_tabla:
En esta sección estableces el nombre de la tabla asociada.
FOR EACH ROW: Establece que el Trigger se ejecute por cada fila en la tabla asociada.
: Define el bloque de sentencias que el Trigger ejecutará al ser
invocado.
Identificadores NEW y OLD en Triggers
Si queremos relacionar el trigger con columnas especificas de una tabla debemos usar los
identificadores OLD y NEW.
OLD indica el valor antiguo de la columna y NEW el valor nuevo que pudiese tomar. Por
ejemplo: OLD.idproducto ó NEW.idproducto.
Si usamos la sentencia UPDATE podremos referirnos a un valor OLD y NEW, ya que
modificaremos registros existentes por nuevos valores. En cambio si usamos INSERT solo
usaremos NEW, ya que su naturaleza es únicamente de insertar nuevos valores a las
columnas. Y si usamos DELETE usaremos OLD debido a que borraremos valores que
existen con anterioridad.
Triggers BEFORE y AFTER
Estas clausulas indican si el Trigger se ejecuta antes o después del evento DML. Hay ciertos
eventos que no son compatibles con estas sentencias.Por ejemplo, si tuvieras un Trigger AFTER que se ejecuta en una sentencia UPDATE, sería
ilógico editar valores nuevos NEW, sabiendo que el evento ya ocurrió. Igual sucedería con
la sentencia INSERT, el Trigger tampoco podría referenciar valores NEW, ya que los valores
que en algún momento fueron NEW, han pasado a ser OLD.
-
8/19/2019 Mysql Procedural SQL - Puro
20/25
¿Qué utilidades tienen los Triggers?
Con los Triggers podemos implementar varios casos de uso que mantengan la integridad de
la base de datos, como Validar in formación , Calcular atr ibutos der ivados , Seguimientos de
movimientos en la base de datos , etc.
Cuando surja una necesidad en donde veas que necesitas que se ejecute una acciónimplícitamente(sin que la ejecutes manualmente) sobre los registros de una tabla, entonces
puedes considerar el uso de un Trigger.
Ejemplo de Trigger BEFORE en la sentencia UPDATE
A continuación veremos un Trigger que valida la edad de un cliente antes de una
sentencia UPDATE. Si por casualidad el nuevo valor es negativo, entonces asignaremos NULL a
este atributo.
DELIMITER //
CREATE TRIGGER cliente_BU_Trigger
BEFORE UPDATE ON cliente FOR EACH ROW
BEGIN
-- La edad es negativa?
IF NEW.edad
Este Trigger se ejecuta antes de haber insertado el registro, lo que nos da el poder de verificar
primero si el nuevo valor de la edad esta en el rango apropiado, si no es así entonces
asignaremosNULL a ese campo. Grandes los Triggers!
Ejemplo de Trigger AFTER en la sentencia UPDATE
Supongamos que tenemos una Tienda de accesor ios para Gamers . Para la actividad de
nuestro negocio hemos creado un sistema de facturación muy sencillo, que registra las
ventas realizadas dentro de una factura que contiene el detalle de las compras.
Nuestra tienda tiene 4 vendedores de turno, los cuales se encargan de registrar las compras
de los clientes en el horario de funcionamiento.
Implementaremos un Trigger que guarde los cambios realizados sobre la
tabla DETALLE_FACTURA de la base de datos realizados por los vendedores.Veamos la solución:
DELIMITER //
CREATE TRIGGER detalle_factura_AU_Trigger
AFTER UPDATE ON detalle_factura FOR EACH ROW
-
8/19/2019 Mysql Procedural SQL - Puro
21/25
BEGIN
INSERT INTO log_updates
(idusuario, descripcion)
VALUES (user ( ),
CONCAT('Se modificó el registro ','(',
OLD.iddetalle,',', OLD.idfactura,',',OLD.idproducto,',',
OLD. precio,',', OLD.unidades,') por ',
'(', NEW.iddetalle,',', NEW.idfactura,',', NEW.idproducto,',',
NEW. precio,',', NEW.unidades,')'));
END//
DELIMITER ;
Con este registro de logs podremos saber si algún vendedor “ocioso” esta alterando las
facturas, lo que lógicamente sería atentar contra las finanzas de nuestro negocio. Cada
registro nos informa el usuario que modificó la tabla DETALLE_FACTURA y muestra una
descripción sobre los cambios en cada columna.
Ejemplo de Trigger BEFORE en al sentencia INSERT
El siguiente ejemplo que te voy a mostrar ¡me encanta!, ya que muestra como mantener la
integridad de una base de datos con respecto a una atributo derivado.
Supón que tienes una Tienda de electrodomésticos y que has implementado un sistema de
facturación. En la base de datos que soporta la información de tu negocio, existen varias
tablas, pero nos vamos a centrar en la tabla PEDIDO y la tabla TOTAL_VENTAS.
TOTAL_VENTAS almacena las ventas totales que se le han hecho a cada cliente del negocio. Es
decir, si el cliente Armado Barreras en una ocasión compró 1000 dolares, luego compró
1250 dolares y hace poco ha vuelto a comprar 2000 dolares, entonces el total vendido a este
cliente es de 4250 dolares.
Pero supongamos que eliminamos el ultimo pedido hecho por este cliente, ¿que pasaría con
el registro en TOTAL_VENTAS ?,…¡exacto!, quedaría desactualizado.Usaremos tres Triggers para solucionar esta situación. Para que cada vez que usemos un
comando DML en la tabla PEDIDO, no tengamos que preocuparnos por actualizar
manualmente TOTAL_VENTAS.
Veamos:
-
8/19/2019 Mysql Procedural SQL - Puro
22/25
-- TRIGGER PARA INSERT
DELIMITER //
CREATE TRIGGER PEDIDO_BI_TRIGGER
BEFORE INSERT ON PEDIDO
FOR EACH ROW
BEGIN
DECLARE cantidad_filas INT;
SELECT COUNT(*)
INTO cantidad_filas
FROM TOTAL_VENTAS
WHERE idcliente= NEW.idcliente;
IF cantidad_filas > 0 THEN
UPDATE TOTAL_VENTAS
SET total=total+ NEW.total
WHERE idcliente= NEW.idcliente;
ELSE
INSERT INTO TOTAL_VENTAS
(idcliente,total)
VALUES( NEW.idcliente, NEW.total);
END IF;
END//
-- TRIGGER PARA UPDATE
CREATE TRIGGER PEDIDO_BU_TRIGGER
BEFORE UPDATE ON PEDIDO
FOR EACH ROW
BEGIN
UPDATE TOTAL_VENTAS
SET total=total+( NEW.total-OLD.total)
WHERE idcliente= NEW.idcliente;
END//
-- TRIGGER PARA DELETE
-
8/19/2019 Mysql Procedural SQL - Puro
23/25
CREATE TRIGGER PEDIDO_BD_TRIGGER
BEFORE DELETE ON PEDIDO
FOR EACH ROW
BEGIN
UPDATE TOTAL_VENTAS
SET total=total-OLD.total
WHERE idcliente=OLD.idcliente;
END//
Con todos ellos mantendremos el total de ventas de cada cliente actualizado dependiendo del
evento realizado sobre un pedido.
Si insertamos un nuevo pedido generado por un cliente existente, entonces vamosrápidamente a la tabla TOTAL_VENTAS y actualizamos el total comprado por ese cliente con
una sencilla suma acumulativa.
Ahora, si cambiamos el monto de un pedido, entonces vamos a TOTAL_VENTAS para descontar
el monto anterior y adicionar el nuevo monto.
Y si eliminamos un pedido de un cliente simplemente descontamos del total acumulado el
monto que con anterioridad habíamos acumulado. ¿Práctico cierto?
Ver la información de un Trigger en MySQL
Si!, usa el comando SHOW CREATE TRIGGER y rápidamente estarás viéndolas
especificaciones de tu Trigger creado. Observa el siguiente ejemplo:
SHOW CREATE TRIGGER futbolista_ai_trigger ;
También puedes ver los Triggers que hay en tu base de datos con:
SHOW TRIGGERS;
Eliminar un Trigger en MySQL DROP, DROP y mas DROP. Como ya sabes usamos este comando para eliminar casi
cualquier cosa en nuestra base de datos:
DROP TRIGGER [IF EXISTS] nombre_trigger
-
8/19/2019 Mysql Procedural SQL - Puro
24/25
Recuerda que podemos adicionar la condicion IF EXISTS para indica que si el Trigger ya
existe, entonces que lo borre.
-
8/19/2019 Mysql Procedural SQL - Puro
25/25