1494 lines
37 KiB
Markdown
1494 lines
37 KiB
Markdown
|
# Stored Procedures
|
||
|
|
||
|
- [MySQL](https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html)
|
||
|
- [MariaDB](https://mariadb.com/kb/en/stored-procedures/)
|
||
|
- [MariaDB Create Procedure](https://mariadb.com/kb/en/create-procedure/)
|
||
|
- MariaDB [W3Schools](https://www.w3schools.blog/procedure-mariadb) procedure
|
||
|
|
||
|
```sql
|
||
|
CREATE
|
||
|
[DEFINER = user]
|
||
|
PROCEDURE sp_name ([proc_parameter[, ...]])
|
||
|
[characteristic ...] routine_body
|
||
|
|
||
|
CREATE
|
||
|
[DEFINER = user]
|
||
|
FUNCTION sp_name ([func_parameter[, ...]])
|
||
|
RETURN type
|
||
|
[characteristic ...] routine_body
|
||
|
|
||
|
proc_parameter:
|
||
|
[ IN | OUT | INOUT ] param_name type
|
||
|
|
||
|
func_parameter:
|
||
|
param_name type
|
||
|
|
||
|
type:
|
||
|
Any valid MySQL data type
|
||
|
|
||
|
characteristic: {
|
||
|
COMMENT 'string'
|
||
|
| LANGUAGE SQL
|
||
|
| [NOT] DETERMINISTIC
|
||
|
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
|
||
|
| SQL SECURITY { DEFINER | INVOKER }
|
||
|
}
|
||
|
|
||
|
routine_body:
|
||
|
Valid SQL routine statement
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CREATE PROCEDURE
|
||
|
<nombre_del_procedimiento> (parámetros)
|
||
|
BEGIN
|
||
|
DECLARE <declaración_de_variables>;
|
||
|
...
|
||
|
<ejecuciones_del_procedimiento>;
|
||
|
...
|
||
|
END;
|
||
|
```
|
||
|
|
||
|
### Ejemplo STORE PROCEDURE
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
|
||
|
DROP PROCEDURE IF EXISTS print_procedure;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE print_procedure ()
|
||
|
BEGIN
|
||
|
SELECT CONCAT("Procedimiento,", " de ", "ejemplo");
|
||
|
END$$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
### Stored Procedures Sintaxis
|
||
|
|
||
|
- Puede tener **letras**, **números** y los caracteres `$` y `_`
|
||
|
- Tamaño máximo: 64 caracteres
|
||
|
- Nombre único
|
||
|
- Case Sensitive
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS hola_pianola;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE hola_pianola ()
|
||
|
BEGIN
|
||
|
SELECT "Hola pianola!";
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
### CALL Procedure
|
||
|
|
||
|
```sql
|
||
|
CALL print_procedure;
|
||
|
+-----------------------------+
|
||
|
| CONCAT("hola,", " pianola") |
|
||
|
+-----------------------------+
|
||
|
| hola, pianola |
|
||
|
+-----------------------------+
|
||
|
```
|
||
|
|
||
|
|
||
|
```sql
|
||
|
CALL hola_pianola;
|
||
|
|
||
|
+---------------+
|
||
|
| Hola pianola! |
|
||
|
+---------------+
|
||
|
| Hola pianola! |
|
||
|
+---------------+
|
||
|
```
|
||
|
|
||
|
#### Otros ejemplos
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS calcular;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE calcular ()
|
||
|
BEGIN
|
||
|
/* Este procedure tiene un comentario */
|
||
|
-- Suma 6+3 y lo mútliplica por 5
|
||
|
# Y muestra el "RESULTADO"
|
||
|
SELECT (6+3)*5 AS RESULTADO;
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
|
||
|
CALL calcular;
|
||
|
|
||
|
+-----------+
|
||
|
| RESULTADO |
|
||
|
+-----------+
|
||
|
| 45 |
|
||
|
+-----------+
|
||
|
```
|
||
|
|
||
|
## Eliminar procedure
|
||
|
|
||
|
```sql
|
||
|
DROPR PROCEDURE jugos_ventas.hola_pianola;
|
||
|
```
|
||
|
|
||
|
### Ejemplo de un procedimiento almacenado mas extenso
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS proc_extenso;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE proc_extenso ()
|
||
|
BEGIN
|
||
|
INSERT INTO tabla_de_productos (
|
||
|
CODIGO_DEL_PRODUCTO,
|
||
|
NOMBRE_DEL_PRODUCTO,
|
||
|
SABOR,
|
||
|
TAMANO,
|
||
|
ENVASE,
|
||
|
PRECIO_DE_LISTA
|
||
|
) VALUES
|
||
|
('1001001','Sabor Alpino','Mango','700 ml','Botella',7.50),
|
||
|
('1001000','Sabor Alpino','Melón','700 ml','Botella',7.50),
|
||
|
('1001002','Sabor Alpino','Guanábana','700 ml','Botella',7.50),
|
||
|
('1001003','Sabor Alpino','Mandarina','700 ml','Botella',7.50),
|
||
|
('1001004','Sabor Alpino','Banana','700 ml','Botella',7.50),
|
||
|
('1001005','Sabor Alpino','Asaí','700 ml','Botella',7.50),
|
||
|
('1001006','Sabor Alpino','Mango','1 Litro','Botella',7.50),
|
||
|
('1001007','Sabor Alpino','Melón','1 Litro','Botella',7.50),
|
||
|
('1001008','Sabor Alpino','Guanábana','1 Litro','Botella',7.50),
|
||
|
('1001009','Sabor Alpino','Mandarina','1 Litro','Botella',7.50),
|
||
|
('1001010','Sabor Alpino','Banana','1 Litro','Botella',7.50),
|
||
|
('1001011','Sabor Alpino','Asaí','1 Litro','Botella',7.50);
|
||
|
|
||
|
SELECT * FROM tabla_de_productos
|
||
|
WHERE NOMBRE_DEL_PRODUCTO LIKE 'Sabor Alp%';
|
||
|
|
||
|
UPDATE tabla_de_productos
|
||
|
SET PRECIO_DE_LISTA = 5
|
||
|
WHERE NOMBRE_DEL_PRODUCTO LIKE 'Sabor Alp%';
|
||
|
|
||
|
SELECT * FROM tabla_de_productos
|
||
|
WHERE NOMBRE_DEL_PRODUCTO LIKE 'Sabor Alp%';
|
||
|
|
||
|
DELETE FROM tabla_de_productos
|
||
|
WHERE NOMBRE_DEL_PRODUCTO LIKE 'Sabor Alp%';
|
||
|
|
||
|
SELECT * FROM tabla_de_productos
|
||
|
WHERE NOMBRE_DEL_PRODUCTO LIKE 'Sabor Alp%';
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL proc_extenso;
|
||
|
```
|
||
|
|
||
|
```txt
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
| CODIGO_DEL_PRODUCTO | NOMBRE_DEL_PRODUCTO | TAMANO | SABOR | ENVASE | PRECIO_DE_LISTA |
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
| 1001000 | Sabor Alpino | 700 ml | Melón | Botella | 7.5 |
|
||
|
| 1001001 | Sabor Alpino | 700 ml | Mango | Botella | 7.5 |
|
||
|
| 1001002 | Sabor Alpino | 700 ml | Guanábana | Botella | 7.5 |
|
||
|
| 1001003 | Sabor Alpino | 700 ml | Mandarina | Botella | 7.5 |
|
||
|
| 1001004 | Sabor Alpino | 700 ml | Banana | Botella | 7.5 |
|
||
|
| 1001005 | Sabor Alpino | 700 ml | Asaí | Botella | 7.5 |
|
||
|
| 1001006 | Sabor Alpino | 1 Litro | Mango | Botella | 7.5 |
|
||
|
| 1001007 | Sabor Alpino | 1 Litro | Melón | Botella | 7.5 |
|
||
|
| 1001008 | Sabor Alpino | 1 Litro | Guanábana | Botella | 7.5 |
|
||
|
| 1001009 | Sabor Alpino | 1 Litro | Mandarina | Botella | 7.5 |
|
||
|
| 1001010 | Sabor Alpino | 1 Litro | Banana | Botella | 7.5 |
|
||
|
| 1001011 | Sabor Alpino | 1 Litro | Asaí | Botella | 7.5 |
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
12 rows in set (0.008 sec)
|
||
|
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
| CODIGO_DEL_PRODUCTO | NOMBRE_DEL_PRODUCTO | TAMANO | SABOR | ENVASE | PRECIO_DE_LISTA |
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
| 1001000 | Sabor Alpino | 700 ml | Melón | Botella | 5 |
|
||
|
| 1001001 | Sabor Alpino | 700 ml | Mango | Botella | 5 |
|
||
|
| 1001002 | Sabor Alpino | 700 ml | Guanábana | Botella | 5 |
|
||
|
| 1001003 | Sabor Alpino | 700 ml | Mandarina | Botella | 5 |
|
||
|
| 1001004 | Sabor Alpino | 700 ml | Banana | Botella | 5 |
|
||
|
| 1001005 | Sabor Alpino | 700 ml | Asaí | Botella | 5 |
|
||
|
| 1001006 | Sabor Alpino | 1 Litro | Mango | Botella | 5 |
|
||
|
| 1001007 | Sabor Alpino | 1 Litro | Melón | Botella | 5 |
|
||
|
| 1001008 | Sabor Alpino | 1 Litro | Guanábana | Botella | 5 |
|
||
|
| 1001009 | Sabor Alpino | 1 Litro | Mandarina | Botella | 5 |
|
||
|
| 1001010 | Sabor Alpino | 1 Litro | Banana | Botella | 5 |
|
||
|
| 1001011 | Sabor Alpino | 1 Litro | Asaí | Botella | 5 |
|
||
|
+---------------------+---------------------+---------+------------+---------+-----------------+
|
||
|
12 rows in set (0.011 sec)
|
||
|
|
||
|
Empty set (0.016 sec)
|
||
|
|
||
|
Query OK, 36 rows affected (0.016 sec)
|
||
|
```
|
||
|
|
||
|
## Variables en procedure
|
||
|
|
||
|
```sql
|
||
|
DECLARE <nombre_de_variable> <datatype> DEFAULT <value>;
|
||
|
```
|
||
|
|
||
|
- **Datatype** es olbligatorio
|
||
|
- **DEFAULT** es opcional, si no se establece, default es **NULL**
|
||
|
- Solo **letras**, **números**, `$` y `_`
|
||
|
- Se pueden declarar varias, con la restricción que sean del mismo tipo
|
||
|
- Tamaño máximo de 255 caracteres
|
||
|
- Nombre único, **case sesitive**
|
||
|
- La declaración termina con `;`
|
||
|
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS mostrar_vars;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE mostrar_vars ()
|
||
|
BEGIN
|
||
|
DECLARE texto CHAR(20) DEFAULT 'Hola';
|
||
|
DECLARE numero INTEGER DEFAULT 789;
|
||
|
DECLARE decimales DECIMAL(5,3) DEFAULT 45.678;
|
||
|
DECLARE fecha DATE DEFAULT '2023-10-10';
|
||
|
DECLARE tiempo TIMESTAMP DEFAULT CURRENT_TIMESTAMP();
|
||
|
SELECT texto, numero, decimales, fecha, tiempo;
|
||
|
/* Modificando valor */
|
||
|
SET numero = 1;
|
||
|
SELECT numero AS numero_modificado;
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
|
||
|
CALL mostrar_vars;
|
||
|
```
|
||
|
|
||
|
```txt
|
||
|
+-------+--------+-----------+------------+---------------------+
|
||
|
| texto | numero | decimales | fecha | tiempo |
|
||
|
+-------+--------+-----------+------------+---------------------+
|
||
|
| Hola | 789 | 45.678 | 2023-10-10 | 2023-10-21 13:11:34 |
|
||
|
+-------+--------+-----------+------------+---------------------+
|
||
|
```
|
||
|
|
||
|
***Crear un Stored Procedure que actualice la edad de los clientes.***
|
||
|
|
||
|
```sql
|
||
|
/* Cálculo de edad */
|
||
|
TIMESTAMPDIFF(YEAR, FECHA_DE_NACIMIENTO, CURDATE()) as EDAD
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE `calcula_edad`()
|
||
|
BEGIN
|
||
|
UPDATE tabla_de_clientes
|
||
|
SET EDAD = TIMESTAMPDIFF(YEAR, FECHA_DE_NACIMIENTO, CURDATE());
|
||
|
END $$
|
||
|
```
|
||
|
|
||
|
## Procedure params
|
||
|
|
||
|
### Ejemplo de procedimiento con variables
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS insert_prod;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE insert_prod (
|
||
|
vcodigo VARCHAR(20),
|
||
|
vnombre VARCHAR(20),
|
||
|
vsabor VARCHAR(20),
|
||
|
vtamano VARCHAR(20),
|
||
|
venvase VARCHAR(20),
|
||
|
vprecio DECIMAL(4,2)
|
||
|
)
|
||
|
BEGIN
|
||
|
/*
|
||
|
DECLARE vcodigo VARCHAR(20) DEFAULT '30030001';
|
||
|
DECLARE vnombre VARCHAR(20) DEFAULT 'Sabor Intenso';
|
||
|
DECLARE vsabor VARCHAR(20) DEFAULT 'Tutti Frutti';
|
||
|
DECLARE vtamano VARCHAR(20) DEFAULT '700 ml';
|
||
|
DECLARE venvase VARCHAR(20) DEFAULT 'Botella PET';
|
||
|
DECLARE vprecio DECIMAL(4,2) DEFAULT '7.25';
|
||
|
*/
|
||
|
INSERT INTO tabla_de_productos (
|
||
|
CODIGO_DEL_PRODUCTO, NOMBRE_DEL_PRODUCTO, SABOR,
|
||
|
TAMANO, ENVASE, PRECIO_DE_LISTA
|
||
|
) VALUES
|
||
|
(vcodigo, vnombre, vtamano, vsabor, venvase, vprecio);
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL insert_prod(
|
||
|
'1000800', 'Sabor del Mar', '700 ml',
|
||
|
'Naranja', 'Botella de Vidrio', 2.25
|
||
|
);
|
||
|
```
|
||
|
|
||
|
***Crear un Stored Procedure para reajustar la comisión de los vendedores.***
|
||
|
***Usando como parámetro el valor (Ej. 0,90).***
|
||
|
|
||
|
```sql
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE `reajuste_comision`(vporcentaje FLOAT)
|
||
|
BEGIN
|
||
|
UPDATE tabla_de_vendedores
|
||
|
SET PORCENTAJE_COMISION = PORCENTAJE_COMISION * (1 + vporcentaje);
|
||
|
END $$
|
||
|
```
|
||
|
|
||
|
#### Ejemplo de procedimiento que establece una variable `a`
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS ejm_params;
|
||
|
|
||
|
DELIMITER //
|
||
|
USE jugos_ventas//
|
||
|
|
||
|
CREATE PROCEDURE ejm_params (OUT param1 INTEGER)
|
||
|
BEGIN
|
||
|
DECLARE total INTEGER DEFAULT 16;
|
||
|
SET param1 = total;
|
||
|
END; //
|
||
|
|
||
|
DELIMITER ;
|
||
|
|
||
|
CALL ejm_params(@a);
|
||
|
|
||
|
SELECT @a;
|
||
|
```
|
||
|
|
||
|
## Manejo de errores en procedures
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS insert_prod;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE insert_prod (
|
||
|
vcodigo VARCHAR(20),
|
||
|
vnombre VARCHAR(20),
|
||
|
vsabor VARCHAR(20),
|
||
|
vtamano VARCHAR(20),
|
||
|
venvase VARCHAR(20),
|
||
|
vprecio DECIMAL(4,2)
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE mensaje VARCHAR(40);
|
||
|
DECLARE EXIT HANDLER FOR 1062
|
||
|
BEGIN
|
||
|
SET mensaje = 'PK duplicada!';
|
||
|
SELECT mensaje AS ERROR_PK;
|
||
|
END;
|
||
|
INSERT INTO tabla_de_productos (
|
||
|
CODIGO_DEL_PRODUCTO, NOMBRE_DEL_PRODUCTO, SABOR,
|
||
|
TAMANO, ENVASE, PRECIO_DE_LISTA
|
||
|
) VALUES
|
||
|
(vcodigo, vnombre, vtamano, vsabor, venvase, vprecio);
|
||
|
SET mensaje = "Producto insertado con exito";
|
||
|
SELECT mensaje AS INFORMACION;
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL insert_prod(
|
||
|
'1000800', 'Sabor del Mar', '700 ml',
|
||
|
'Naranja', 'Botella de Vidrio', 2.25
|
||
|
);
|
||
|
|
||
|
+---------------+
|
||
|
| ERROR_PK |
|
||
|
+---------------+
|
||
|
| PK duplicada! |
|
||
|
+---------------+
|
||
|
|
||
|
CALL insert_prod(
|
||
|
'1000801', 'Sabor del Mar', '900 ml',
|
||
|
'Naranja', 'Botella de Vidrio', 2.45
|
||
|
);
|
||
|
|
||
|
+------------------------------+
|
||
|
| INFORMACION |
|
||
|
+------------------------------+
|
||
|
| Producto insertado con exito |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
### Ejemplo rutine que muestra el sabor del produco insertado
|
||
|
|
||
|
```sql
|
||
|
USE jugos_ventas;
|
||
|
DROP PROCEDURE IF EXISTS mostrar_sabor;
|
||
|
|
||
|
DELIMITER $$
|
||
|
USE jugos_ventas$$
|
||
|
CREATE PROCEDURE mostrar_sabor (
|
||
|
vcodigo VARCHAR(20) COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vsabor VARCHAR(20);
|
||
|
SELECT SABOR INTO vsabor FROM tabla_de_productos
|
||
|
WHERE CODIGO_DEL_PRODUCTO = `vcodigo`;
|
||
|
SELECT vsabor AS SABOR;
|
||
|
END$$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL mostrar_sabor('1000800');
|
||
|
|
||
|
+---------+
|
||
|
| SABOR |
|
||
|
+---------+
|
||
|
| Naranja |
|
||
|
+---------+
|
||
|
```
|
||
|
|
||
|
***Crear una variable `N_FACTURAS` y asignar el número de facturas del día***
|
||
|
***`01/01/2017` y mostrar el valor de la variable.***
|
||
|
|
||
|
```sql
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE `cantidad_facturas`()
|
||
|
BEGIN
|
||
|
DECLARE N_FACTURAS INTEGER;
|
||
|
SELECT COUNT(*) INTO N_FACTURAS FROM facturas WHERE
|
||
|
FECHA_VENTA = '2017-01-01';
|
||
|
SELECT N_FACTURAS;
|
||
|
END $$
|
||
|
```
|
||
|
|
||
|
## IF THEN ELSE
|
||
|
|
||
|
```sql
|
||
|
IF <condition> THEN
|
||
|
<if_statements>;
|
||
|
ELSE
|
||
|
<else_statements>;
|
||
|
END IF
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS edad_clientes;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE edad_clientes(
|
||
|
vdni VARCHAR(20) COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(50);
|
||
|
DECLARE vfecha DATE;
|
||
|
SELECT fecha_de_nacimiento INTO vfecha
|
||
|
FROM tabla_de_clientes WHERE dni=vdni;
|
||
|
IF
|
||
|
vfecha < '19950101'
|
||
|
THEN
|
||
|
SET vresultado = 'Cliente Antiguo';
|
||
|
ELSE
|
||
|
SET vresultado = 'Cliente Normal';
|
||
|
END IF;
|
||
|
SELECT vresultado AS TIPO_CLIENTE;
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```
|
||
|
CALL edad_clientes('1471156710');
|
||
|
+-----------------+
|
||
|
| TIPO_CLIENTE |
|
||
|
+-----------------+
|
||
|
| Cliente Antiguo |
|
||
|
+-----------------+
|
||
|
|
||
|
CALL edad_clientes('3623344710');
|
||
|
+----------------+
|
||
|
| TIPO_CLIENTE |
|
||
|
+----------------+
|
||
|
| Cliente Normal |
|
||
|
+----------------+
|
||
|
```
|
||
|
|
||
|
***Crear un Stored Procedure que, según una fecha dada, calcule el número***
|
||
|
***de facturas. Si el resultado son más de 70 facturas mostar el mensaje:***
|
||
|
***'Muchas facturas'. En otro caso, el mensaje será 'Pocas facturas'.***
|
||
|
***En ambos casos se debe mostrar el número de facturas***
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS cant_facturas;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE cant_facturas(vfecha DATE)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(50);
|
||
|
DECLARE vfacturas INTEGER;
|
||
|
SELECT COUNT(matricula) INTO vfacturas
|
||
|
FROM facturas WHERE fecha_venta=vfecha;
|
||
|
IF
|
||
|
vfacturas > 70
|
||
|
THEN
|
||
|
SET vresultado = CONCAT('Muchas Facturas: ', vfacturas);
|
||
|
# SET vresultado = 'Muchas Facturas: ';
|
||
|
ELSE
|
||
|
SET vresultado = CONTACT('Pocas Facturas: ', vfacturas);
|
||
|
# SET vresultado = 'Pocas Facturas: ';
|
||
|
END IF;
|
||
|
SELECT vresultado AS FACTURAS_EN_FECHA;
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL cant_facturas('2018-01-01');
|
||
|
+---------------------+
|
||
|
| FACTURAS_EN_FECHA |
|
||
|
+---------------------+
|
||
|
| Muchas Facturas: 87 |
|
||
|
+---------------------+
|
||
|
```
|
||
|
|
||
|
### ELSE IF
|
||
|
|
||
|
```sql
|
||
|
IF <condition> THEN
|
||
|
<if_statements>;
|
||
|
ELSEIF <condition>
|
||
|
<elseif_statements>;
|
||
|
(...)
|
||
|
ELSEIF <condition>
|
||
|
<elseif_statements>;
|
||
|
ELSE
|
||
|
<else_statements>;
|
||
|
END IF;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
/*
|
||
|
precio >= 12 producto costoso
|
||
|
precio >= 12 < 12 producto asequible
|
||
|
precio < 7 producto barato
|
||
|
*/
|
||
|
DROP PROCEDURE IF EXISTS clasific_precio;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE clasific_precio(
|
||
|
vcodigo VARCHAR(20)
|
||
|
COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(40);
|
||
|
DECLARE vprecio FLOAT;
|
||
|
|
||
|
SELECT precio_de_lista INTO vprecio
|
||
|
FROM tabla_de_productos
|
||
|
WHERE codigo_del_producto = vcodigo;
|
||
|
|
||
|
IF vprecio >= 12 THEN
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Costoso: $', vprecio, '.-'
|
||
|
);
|
||
|
ELSEIF vprecio >= 7 AND vprecio < 12 THEN
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Asequible: $', vprecio, '.-'
|
||
|
);
|
||
|
ELSE
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Barato: $', vprecio, '.-'
|
||
|
);
|
||
|
END IF;
|
||
|
SELECT vresultado AS "Clasificación por precio";
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasific_precio('1000800');
|
||
|
+--------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+--------------------------+
|
||
|
| Producto Barato: $2.25.- |
|
||
|
+--------------------------+
|
||
|
|
||
|
CALL clasific_precio('783663');
|
||
|
+-----------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+-----------------------------+
|
||
|
| Producto Asequible: $7.71.- |
|
||
|
+-----------------------------+
|
||
|
|
||
|
CALL clasific_precio('1004327');
|
||
|
+----------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+----------------------------+
|
||
|
| Producto Costoso: $19.51.- |
|
||
|
+----------------------------+
|
||
|
```
|
||
|
|
||
|
***Crear un Stored Procedure `comparacion_ventas` que compare las ventas***
|
||
|
***en entre 2 fechas distintas. Si el porcentaje de variación es mayor al***
|
||
|
***10% debe retornar 'Verde'. Si está entre -10% y 10% debe restornar***
|
||
|
***'Amarillo'. Si es menor al -10% debe retornar 'Rojo'***
|
||
|
|
||
|
```sql
|
||
|
/*
|
||
|
total > 10% Verde
|
||
|
precio <= 10% y >= -10% Amarillo
|
||
|
precio < -10% Rojo
|
||
|
*/
|
||
|
DROP PROCEDURE IF EXISTS comparacion_ventas;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE comparacion_ventas(
|
||
|
vfecha1 DATE,
|
||
|
vfecha2 DATE
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(50);
|
||
|
DECLARE vtotal1 INTEGER;
|
||
|
DECLARE vtotal2 INTEGER;
|
||
|
DECLARE vtotal FLOAT;
|
||
|
|
||
|
SELECT SUM(B.CANTIDAD * B.PRECIO) INTO vtotal1
|
||
|
FROM facturas A INNER JOIN items_facturas B
|
||
|
ON A.NUMERO = B.NUMERO
|
||
|
WHERE A.FECHA_VENTA = vfecha1;
|
||
|
|
||
|
SELECT SUM(B.CANTIDAD * B.PRECIO) INTO vtotal2
|
||
|
FROM facturas A INNER JOIN items_facturas B
|
||
|
ON A.NUMERO = B.NUMERO
|
||
|
WHERE A.FECHA_VENTA = vfecha2;
|
||
|
|
||
|
SELECT ROUND(((vtotal2*100)/vtotal1)-100, 2) INTO vtotal;
|
||
|
|
||
|
IF vtotal > 10 THEN
|
||
|
SET vresultado = CONCAT('Verde: ', vtotal, '%');
|
||
|
ELSEIF vtotal >= -10 AND vtotal <= 10 THEN
|
||
|
SET vresultado = CONCAT('Amarillo: ', vtotal, '%');
|
||
|
ELSE
|
||
|
SET vresultado = CONCAT('Rojo: ', vtotal, '%');
|
||
|
END IF;
|
||
|
SELECT vresultado AS "Porcentaje variación ventas";
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2016-12-31','2017-12-31');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Verde: 28.23% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2018-03-28','2018-03-27');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Amarillo: -2.2% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2018-03-28','2015-03-28');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Rojo: -41.86% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
## CASE
|
||
|
|
||
|
```sql
|
||
|
CASE <selector>
|
||
|
WHEN <selector_value_1> THEN <then_statement_1>;
|
||
|
WHEN <selector_value_2> THEN <then_statement_2>;
|
||
|
(...)
|
||
|
WHEN <selector_value_n> THEN <then_statement_n>;
|
||
|
[ELSE <else_statements>]
|
||
|
END CASE;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
/*
|
||
|
Maracuya = Rico
|
||
|
Frutilla = Rico
|
||
|
Uva = Rico
|
||
|
Sandía = Normal
|
||
|
Mango = Normal
|
||
|
Otros = Comunes
|
||
|
*/
|
||
|
DROP PROCEDURE IF EXISTS clasif_sabores;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE clasif_sabores(
|
||
|
vcodigo VARCHAR(20)
|
||
|
COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE msg_error VARCHAR(40);
|
||
|
DECLARE vresultado VARCHAR(50);
|
||
|
DECLARE vsabor VARCHAR(50);
|
||
|
# Se comenta el ELSE para testear HANDLER CASE NOT FOUND
|
||
|
#DECLARE CONTINUE HANDLER FOR 1339
|
||
|
DECLARE EXIT HANDLER FOR 1339
|
||
|
BEGIN
|
||
|
SET msg_error = "Sabor sin clasificar!";
|
||
|
SELECT msg_error AS "ERROR CASE NOT FOUND";
|
||
|
END;
|
||
|
|
||
|
SELECT sabor INTO vsabor
|
||
|
FROM tabla_de_productos
|
||
|
WHERE codigo_del_producto = vcodigo;
|
||
|
|
||
|
CASE vsabor
|
||
|
WHEN 'Maracuya' THEN SELECT 'Rico' INTO vresultado;
|
||
|
WHEN 'Limón' THEN SELECT 'Rico' INTO vresultado;
|
||
|
WHEN 'Frutilla' THEN SELECT 'Rico' INTO vresultado;
|
||
|
WHEN 'Uva' THEN SELECT 'Rico' INTO vresultado;
|
||
|
WHEN 'Sandía' THEN SELECT 'Normal' INTO vresultado;
|
||
|
WHEN 'Mango' THEN SELECT 'Normal' INTO vresultado;
|
||
|
#ELSE SELECT 'Común' INTO vresultado;
|
||
|
END CASE;
|
||
|
SELECT CONCAT(vsabor, ': ', vresultado) AS "Clasificación de sabor";
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_sabores('1042712');
|
||
|
+-------------------------+
|
||
|
| Clasificación de sabor |
|
||
|
+-------------------------+
|
||
|
| Limón: Rico |
|
||
|
+-------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_sabores('1004327');
|
||
|
+-------------------------+
|
||
|
| Clasificación de sabor |
|
||
|
+-------------------------+
|
||
|
| Sandía: Normal |
|
||
|
+-------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_sabores('394479');
|
||
|
+-------------------------+
|
||
|
| Clasificación de sabor |
|
||
|
+-------------------------+
|
||
|
| Cereza: Común |
|
||
|
+-------------------------+
|
||
|
```
|
||
|
|
||
|
### CASE condicional
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS clasif_precio;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE clasif_precio(
|
||
|
vcodigo VARCHAR(20)
|
||
|
COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(40);
|
||
|
DECLARE vprecio FLOAT;
|
||
|
|
||
|
SELECT precio_de_lista INTO vprecio
|
||
|
FROM tabla_de_productos
|
||
|
WHERE codigo_del_producto = vcodigo;
|
||
|
|
||
|
CASE
|
||
|
WHEN vprecio >= 12 THEN
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Costoso: $', vprecio, '.-'
|
||
|
);
|
||
|
WHEN vprecio >= 7 AND vprecio < 12 THEN
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Asequible: $', vprecio, '.-'
|
||
|
);
|
||
|
ELSE
|
||
|
SET vresultado = CONCAT(
|
||
|
'Producto Barato: $', vprecio, '.-'
|
||
|
);
|
||
|
END CASE;
|
||
|
SELECT vresultado AS "Clasificación por precio";
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_precio('1013793');
|
||
|
+----------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+----------------------------+
|
||
|
| Producto Costoso: $24.01.- |
|
||
|
+----------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_precio('1096818');
|
||
|
+-----------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+-----------------------------+
|
||
|
| Producto Asequible: $7.71.- |
|
||
|
+-----------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL clasif_precio('1000801');
|
||
|
+---------------------------+
|
||
|
| Clasificación por precio |
|
||
|
+---------------------------+
|
||
|
| Producto Barato: $2.45.- |
|
||
|
+---------------------------+
|
||
|
```
|
||
|
|
||
|
***Modificar SP `comparacion_ventas` usando CASE***
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS compara_ventas;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE compara_ventas(
|
||
|
vfecha1 DATE,
|
||
|
vfecha2 DATE
|
||
|
)
|
||
|
BEGIN
|
||
|
DECLARE vresultado VARCHAR(50);
|
||
|
DECLARE vtotal1 INTEGER;
|
||
|
DECLARE vtotal2 INTEGER;
|
||
|
DECLARE vtotal FLOAT;
|
||
|
|
||
|
SELECT SUM(B.CANTIDAD * B.PRECIO) INTO vtotal1
|
||
|
FROM facturas A INNER JOIN items_facturas B
|
||
|
ON A.NUMERO = B.NUMERO
|
||
|
WHERE A.FECHA_VENTA = vfecha1;
|
||
|
|
||
|
SELECT SUM(B.CANTIDAD * B.PRECIO) INTO vtotal2
|
||
|
FROM facturas A INNER JOIN items_facturas B
|
||
|
ON A.NUMERO = B.NUMERO
|
||
|
WHERE A.FECHA_VENTA = vfecha2;
|
||
|
|
||
|
SELECT ROUND(((vtotal2*100)/vtotal1)-100, 2) INTO vtotal;
|
||
|
|
||
|
CASE
|
||
|
WHEN vtotal > 10 THEN
|
||
|
SET vresultado = CONCAT('Verde: ', vtotal, '%');
|
||
|
WHEN vtotal >= -10 AND vtotal <= 10 THEN
|
||
|
SET vresultado = CONCAT('Amarillo: ', vtotal, '%');
|
||
|
ELSE
|
||
|
SET vresultado = CONCAT('Rojo: ', vtotal, '%');
|
||
|
END CASE;
|
||
|
SELECT vresultado AS "Porcentaje variación ventas";
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2016-12-31','2017-12-31');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Verde: 28.23% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2018-03-28','2018-03-27');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Amarillo: -2.2% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL comparacion_ventas('2018-03-28','2015-03-28');
|
||
|
+------------------------------+
|
||
|
| Porcentaje variación ventas |
|
||
|
+------------------------------+
|
||
|
| Rojo: -41.86% |
|
||
|
+------------------------------+
|
||
|
```
|
||
|
|
||
|
## WHILE
|
||
|
|
||
|
```sql
|
||
|
WHILE <condition>
|
||
|
DO <statements>;
|
||
|
END WHILE;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS looping;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE looping(vinicial INT, vfinal INT)
|
||
|
BEGIN
|
||
|
DECLARE vcontador INT;
|
||
|
SET vcontador = vinicial;
|
||
|
CREATE TABLE tb_looping (ID INT);
|
||
|
WHILE vcontador <= vfinal
|
||
|
DO
|
||
|
INSERT INTO tb_looping VALUES(vcontador);
|
||
|
SET vcontador = vcontador+1;
|
||
|
END WHILE;
|
||
|
SELECT * FROM tb_looping;
|
||
|
DROP TABLE tb_looping;
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL looping(1,5);
|
||
|
+------+
|
||
|
| ID |
|
||
|
+------+
|
||
|
| 1 |
|
||
|
| 2 |
|
||
|
| 3 |
|
||
|
| 4 |
|
||
|
| 5 |
|
||
|
+------+
|
||
|
```
|
||
|
|
||
|
***Crear un SP que, a partir del día `01/01/2017`, cuente el número de***
|
||
|
***facturas hasta el día `10/01/2017`. Debe mostrar la fecha y el número***
|
||
|
***de facturas día tras día***
|
||
|
|
||
|
#### Solución propuesta
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS loop_date;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE loop_date(vfecha_inicial DATE, vfecha_final DATE)
|
||
|
BEGIN
|
||
|
CREATE TEMPORARY TABLE informe (Fecha DATE, Facturas_Emitidas INT);
|
||
|
WHILE vfecha_inicial <= vfecha_final
|
||
|
DO
|
||
|
INSERT INTO informe
|
||
|
SELECT fecha_venta, COUNT(numero) FROM facturas
|
||
|
WHERE fecha_venta = vfecha_inicial;
|
||
|
SET vfecha_inicial = ADDDATE(vfecha_inicial, INTERVAL 1 DAY);
|
||
|
END WHILE;
|
||
|
SELECT * FROM informe;
|
||
|
DROP TABLE informe;
|
||
|
END $$
|
||
|
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL loop_date('2017-01-01','2017-01-10');
|
||
|
+------------+-------------------+
|
||
|
| Fecha | Facturas_Emitidas |
|
||
|
+------------+-------------------+
|
||
|
| 2017-01-01 | 74 |
|
||
|
| 2017-01-02 | 77 |
|
||
|
| 2017-01-03 | 81 |
|
||
|
| 2017-01-04 | 71 |
|
||
|
| 2017-01-05 | 65 |
|
||
|
| 2017-01-06 | 75 |
|
||
|
| 2017-01-07 | 82 |
|
||
|
| 2017-01-08 | 80 |
|
||
|
| 2017-01-09 | 85 |
|
||
|
| 2017-01-10 | 72 |
|
||
|
+------------+-------------------
|
||
|
```
|
||
|
|
||
|
#### Solución
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS suma_dias_facturas;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE suma_dias_facturas()
|
||
|
BEGIN
|
||
|
DECLARE fecha_inicial DATE;
|
||
|
DECLARE fecha_final DATE;
|
||
|
DECLARE n_facturas INT;
|
||
|
SET fecha_inicial = '20170101';
|
||
|
SET fecha_final = '20170110';
|
||
|
WHILE fecha_inicial <= fecha_final
|
||
|
DO
|
||
|
SELECT COUNT(*) INTO n_facturas FROM facturas
|
||
|
WHERE FECHA_VENTA = fecha_inicial;
|
||
|
SELECT concat(
|
||
|
DATE_FORMAT(fecha_inicial, '%d/%m/%Y'),
|
||
|
'-' , CAST(n_facturas AS CHAR(50))
|
||
|
) AS RESULTADO;
|
||
|
SELECT ADDDATE(fecha_inicial, INTERVAL 1 DAY) INTO fecha_inicial;
|
||
|
END WHILE;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
## Problemas con SELECT INTO
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS problema_select_into;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE problema_select_into()
|
||
|
BEGIN
|
||
|
DECLARE vnombre VARCHAR(50);
|
||
|
SELECT nombre INTO vnombre FROM tabla_de_clientes;
|
||
|
SELECT vnombre;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
|
||
|
CALL problema_select_into();
|
||
|
ERROR 1172 (42000): Result consisted of more than one row
|
||
|
```
|
||
|
|
||
|
## CURSOR
|
||
|
|
||
|
Un **CURSOR** es una estructura que permite la interación línea a línea
|
||
|
mediante un orden determinado
|
||
|
|
||
|
#### Fases para utilizar Cursor
|
||
|
|
||
|
- **Declaración:** Definir la consulta que será depositada en el cursor
|
||
|
- **Apertura:** Abrir el cursor para recorrerlo línea a línea
|
||
|
- **Recorrido:** Línea a línea hasta el final
|
||
|
- **Cierre:** Cierre del cursor
|
||
|
- **Limpieza:** Limpiar el cursor de la memoria
|
||
|
|
||
|
#### Tabla_1
|
||
|
|
||
|
| Codigo | Nombre | Valor |
|
||
|
| - | - | - |
|
||
|
| 1 | Juan | 2 |
|
||
|
| 2 | José | 67 |
|
||
|
| 3 | María | 7 |
|
||
|
| 4 | Lucia | 54 |
|
||
|
|
||
|
```sql
|
||
|
DECLARE @nombre VARCHAR(10)
|
||
|
DECLARE CURSOR_1 CURSOR FOR
|
||
|
SELECT NOMBRE FROM tabla_1;
|
||
|
OPEN CURSOR_1;
|
||
|
FETCH CURSOR_1 INTO @nombre;
|
||
|
FETCH CURSOR_1 INTO @nombre;
|
||
|
FETCH CURSOR_1 INTO @nombre;
|
||
|
FETCH CURSOR_1 INTO @nombre;
|
||
|
CLOSE CURSOR_1;
|
||
|
```
|
||
|
|
||
|
#### Ejemplo CURSOR
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS ejm_cursor;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE ejm_cursor()
|
||
|
BEGIN
|
||
|
DECLARE vnombre VARCHAR(50);
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT nombre FROM tabla_de_clientes LIMIT 4;
|
||
|
OPEN c;
|
||
|
FETCH c INTO vnombre;
|
||
|
SELECT vnombre;
|
||
|
FETCH c INTO vnombre;
|
||
|
SELECT vnombre;
|
||
|
FETCH c INTO vnombre;
|
||
|
SELECT vnombre;
|
||
|
FETCH c INTO vnombre;
|
||
|
SELECT vnombre;
|
||
|
CLOSE c;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL ejm_cursor;
|
||
|
+---------------+
|
||
|
| vnombre |
|
||
|
+---------------+
|
||
|
| Erica Carvajo |
|
||
|
+---------------+
|
||
|
|
||
|
+--------------+
|
||
|
| vnombre |
|
||
|
+--------------+
|
||
|
| Marcos Rosas |
|
||
|
+--------------+
|
||
|
|
||
|
+--------------+
|
||
|
| vnombre |
|
||
|
+--------------+
|
||
|
| Jorge Castro |
|
||
|
+--------------+
|
||
|
|
||
|
+-------------+
|
||
|
| vnombre |
|
||
|
+-------------+
|
||
|
| Abel Pintos |
|
||
|
+-------------+
|
||
|
```
|
||
|
|
||
|
### Iterando el CURSOR
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS iter_cursor;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE iter_cursor()
|
||
|
BEGIN
|
||
|
DECLARE fin_c BIT(1) DEFAULT b'0';
|
||
|
DECLARE vnombre VARCHAR(50);
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT nombre FROM tabla_de_clientes;
|
||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||
|
SET fin_c = b'1';
|
||
|
OPEN c;
|
||
|
WHILE fin_c = b'0' DO
|
||
|
FETCH c INTO vnombre;
|
||
|
IF fin_c = 0 THEN
|
||
|
SELECT vnombre;
|
||
|
END IF;
|
||
|
END WHILE;
|
||
|
CLOSE c;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL iter_cursor;
|
||
|
+---------------+
|
||
|
| vnombre |
|
||
|
+---------------+
|
||
|
| Erica Carvajo |
|
||
|
+---------------+
|
||
|
|
||
|
+--------------+
|
||
|
| vnombre |
|
||
|
+--------------+
|
||
|
| Marcos Rosas |
|
||
|
+--------------+
|
||
|
|
||
|
+--------------+
|
||
|
| vnombre |
|
||
|
+--------------+
|
||
|
| Jorge Castro |
|
||
|
+--------------+
|
||
|
|
||
|
...
|
||
|
```
|
||
|
|
||
|
***Crear un SP usando un cursor para hallar el valor total de todos los***
|
||
|
***créditos, de todos los clientes***
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS total_creditos;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE total_creditos()
|
||
|
BEGIN
|
||
|
DECLARE fin_c BIT(1) DEFAULT b'0';
|
||
|
DECLARE vcred_total FLOAT DEFAULT 0;
|
||
|
DECLARE vcred_temp FLOAT DEFAULT 0;
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT limite_de_credito FROM tabla_de_clientes;
|
||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||
|
SET fin_c = b'1';
|
||
|
OPEN c;
|
||
|
WHILE fin_c = b'0' DO
|
||
|
FETCH c INTO vcred_temp;
|
||
|
IF fin_c = 0 THEN
|
||
|
SET vcred_total = vcred_total + vcred_temp;
|
||
|
END IF;
|
||
|
END WHILE;
|
||
|
CLOSE c;
|
||
|
SELECT vcred_total AS "Limite de Credito TOTAL";
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL total_creditos;
|
||
|
+-------------------------+
|
||
|
| Limite de Credito TOTAL |
|
||
|
+-------------------------+
|
||
|
| 1780000 |
|
||
|
+-------------------------+
|
||
|
```
|
||
|
|
||
|
### Asignación de multiples campos al CURSOR
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS cursor_multicampo;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE cursor_multicampo()
|
||
|
BEGIN
|
||
|
DECLARE fin_c BIT(1) DEFAULT b'0';
|
||
|
DECLARE vbarrio, vciudad, vcodp VARCHAR(50);
|
||
|
DECLARE vnombre, vdireccion VARCHAR(150);
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT nombre, direccion_1, barrio, ciudad, cp
|
||
|
FROM tabla_de_clientes;
|
||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||
|
SET fin_c = b'1';
|
||
|
OPEN c;
|
||
|
WHILE fin_c = b'0' DO
|
||
|
FETCH c INTO vnombre, vdireccion, vbarrio, vciudad, vcodp;
|
||
|
IF fin_c = b'0' THEN
|
||
|
SELECT CONCAT(vnombre, ', ', vdireccion, ', ', vbarrio, ', ',
|
||
|
vciudad, ', ', vcodp) AS Muticampos;
|
||
|
END IF;
|
||
|
END WHILE;
|
||
|
CLOSE c;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL cursor_multicampo;
|
||
|
+------------------------------------------------------------------------------+
|
||
|
| Muticampos |
|
||
|
+------------------------------------------------------------------------------+
|
||
|
| Erica Carvajo, Heriberto Frías 1107, Del Valle, Ciudad de México, 80012212 |
|
||
|
+------------------------------------------------------------------------------+
|
||
|
|
||
|
+-----------------------------------------------------------------------+
|
||
|
| Muticampos |
|
||
|
+-----------------------------------------------------------------------+
|
||
|
| Marcos Rosas, Av. Universidad, Del Valle, Ciudad de México, 22002012 |
|
||
|
+-----------------------------------------------------------------------+
|
||
|
|
||
|
+---------------------------------------------------------------------------------+
|
||
|
| Muticampos |
|
||
|
+---------------------------------------------------------------------------------+
|
||
|
| Jorge Castro, Federal México-Toluca 5690, Locaxco, Ciudad de México, 22012002 |
|
||
|
+---------------------------------------------------------------------------------+
|
||
|
|
||
|
...
|
||
|
```
|
||
|
|
||
|
***Crear un SP usando un cursor para hallar el valor total de la***
|
||
|
***facturación para un determinado mes y año.***
|
||
|
|
||
|
#### Solución propuesta
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS facturacion_mes_ano;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE facturacion_mes_ano(ano_mes VARCHAR(10))
|
||
|
BEGIN
|
||
|
DECLARE fin_c BIT(1) DEFAULT b'0';
|
||
|
DECLARE vcantidad INT;
|
||
|
DECLARE vprecio FLOAT;
|
||
|
DECLARE vtotal FLOAT DEFAULT 0;
|
||
|
DECLARE vfecha DATE;
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT IFa.cantidad, IFa.precio
|
||
|
FROM items_facturas IFa
|
||
|
INNER JOIN facturas F ON F.numero = IFa.numero
|
||
|
WHERE MONTH(F.fecha_venta) = MONTH(vfecha)
|
||
|
AND YEAR(F.fecha_venta) = YEAR(vfecha);
|
||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||
|
SET fin_c = b'1';
|
||
|
SET vfecha = DATE(CONCAT(ano_mes, '-01'));
|
||
|
OPEN c;
|
||
|
WHILE fin_c = b'0' DO
|
||
|
FETCH c INTO vcantidad, vprecio;
|
||
|
IF fin_c = b'0' THEN
|
||
|
SET vtotal = vtotal+(vcantidad*vprecio);
|
||
|
END IF;
|
||
|
END WHILE;
|
||
|
CLOSE c;
|
||
|
SELECT ano_mes AS "Año-Mes",
|
||
|
CONCAT('$ ', vtotal, '.-') AS "Venta Total";
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL facturacion_mes_ano('2017-01');
|
||
|
+----------+-------------+
|
||
|
| Año-Mes | Venta Total |
|
||
|
+----------+-------------+
|
||
|
| 2017-01 | $3838320.- |
|
||
|
+----------+-------------+
|
||
|
```
|
||
|
|
||
|
#### Solución
|
||
|
|
||
|
```sql
|
||
|
DROP PROCEDURE IF EXISTS campo_adicional;
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE campo_adicional()
|
||
|
BEGIN
|
||
|
DECLARE cantidad INT;
|
||
|
DECLARE precio FLOAT;
|
||
|
DECLARE facturacion_acumulada FLOAT;
|
||
|
DECLARE fin_cursor INT;
|
||
|
DECLARE c CURSOR FOR
|
||
|
SELECT IFa.CANTIDAD, IFa.PRECIO FROM items_facturas IFa
|
||
|
INNER JOIN facturas F ON F.NUMERO = IFa.NUMERO
|
||
|
WHERE MONTH(F.FECHA_VENTA) = 1
|
||
|
AND YEAR(F.FECHA_VENTA) = 2017;
|
||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||
|
SET fin_cursor = 1;
|
||
|
OPEN c;
|
||
|
SET fin_cursor = 0;
|
||
|
SET facturacion_acumulada = 0;
|
||
|
WHILE fin_cursor = 0 DO
|
||
|
FETCH c INTO cantidad, precio;
|
||
|
IF fin_cursor = 0 THEN
|
||
|
SET facturacion_acumulada =
|
||
|
facturacion_acumulada + (cantidad * precio);
|
||
|
END IF;
|
||
|
END WHILE;
|
||
|
CLOSE c;
|
||
|
SELECT facturacion_acumulada;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
CALL campo_adicional;
|
||
|
+-----------------------+
|
||
|
| facturacion_acumulada |
|
||
|
+-----------------------+
|
||
|
| 3838320 |
|
||
|
+-----------------------+
|
||
|
```
|
||
|
|
||
|
## FUNCTION
|
||
|
|
||
|
```sql
|
||
|
CREATE FUNCTION function_name (parameters)
|
||
|
RETURNS datatype;
|
||
|
BEGIN
|
||
|
DECLARE <declaration_statement>;
|
||
|
(...)
|
||
|
<excecutable_statement>;
|
||
|
(...)
|
||
|
RETURN <statement>
|
||
|
(...)
|
||
|
END;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
DROP FUNCTION IF EXISTS f_clas_sabores;
|
||
|
DELIMITER $$
|
||
|
CREATE FUNCTION f_clas_sabores(vsabor VARCHAR(20))
|
||
|
RETURNS VARCHAR(40) COLLATE 'utf8mb4_uca1400_as_ci'
|
||
|
BEGIN
|
||
|
DECLARE vretorno VARCHAR(40) DEFAULT '';
|
||
|
CASE vsabor
|
||
|
WHEN 'Maracuya' THEN SET vretorno = 'Rico';
|
||
|
WHEN 'Limón' THEN SET vretorno = 'Rico';
|
||
|
WHEN 'Frutilla' THEN SET vretorno = 'Rico';
|
||
|
WHEN 'Uva' THEN SET vretorno = 'Rico';
|
||
|
WHEN 'Sandía' THEN SET vretorno = 'Normal';
|
||
|
WHEN 'Mango' THEN SET vretorno = 'Normal';
|
||
|
ELSE SET vretorno = 'Común';
|
||
|
END CASE;
|
||
|
RETURN vretorno;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
SELECT f_clas_sabores('Sandía') AS "Clasificación";
|
||
|
+----------------+
|
||
|
| Clasificación |
|
||
|
+----------------+
|
||
|
| Normal |
|
||
|
+----------------+
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
SELECT nombre_del_producto, sabor, f_clas_sabores(sabor) AS "Clasificación"
|
||
|
FROM tabla_de_productos;
|
||
|
+---------------------+-----------------+----------------+
|
||
|
| nombre_del_producto | sabor | Clasificación |
|
||
|
+---------------------+-----------------+----------------+
|
||
|
| Sabor del Mar | Naranja | Común |
|
||
|
| Sabor del Mar | Naranja | Común |
|
||
|
| Sabor da Montaña | Uva | Rico |
|
||
|
...
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
SELECT nombre_del_producto, sabor
|
||
|
FROM tabla_de_productos
|
||
|
WHERE f_clas_sabores(SABOR) = 'Normal';
|
||
|
+---------------------+---------+
|
||
|
| nombre_del_producto | sabor |
|
||
|
+---------------------+---------+
|
||
|
| Vida del Campo | Sandía |
|
||
|
| Light | Sandía |
|
||
|
| Verano | Mango |
|
||
|
| Refrescante | Mango |
|
||
|
| Refrescante | Mango |
|
||
|
| Verano | Mango |
|
||
|
| Vida del Campo | Sandía |
|
||
|
| Refrescante | Mango |
|
||
|
| Light | Sandía |
|
||
|
+---------------------+---------+
|
||
|
```
|
||
|
|
||
|
***Transformar el sgte. SP en una función que recibe como parámetro la***
|
||
|
***fecha y retorna el número de facturas***
|
||
|
|
||
|
```sql
|
||
|
DELIMITER $$
|
||
|
CREATE PROCEDURE `sp_numero_facturas` ()
|
||
|
BEGIN
|
||
|
DECLARE n_facturas INT;
|
||
|
SELECT COUNT(*) INTO n_facturas FROM facturas
|
||
|
WHERE FECHA_VENTA = '20170101';
|
||
|
SELECT n_facturas;
|
||
|
END $$
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
DROP FUNCTION IF EXISTS f_cantidad_facturas;
|
||
|
DELIMITER $$
|
||
|
CREATE FUNCTION f_cantidad_facturas(fecha DATE)
|
||
|
RETURNS INT
|
||
|
BEGIN
|
||
|
DECLARE n_facturas INT;
|
||
|
SELECT COUNT(*) INTO n_facturas FROM facturas
|
||
|
WHERE FECHA_VENTA = fecha;
|
||
|
RETURN n_facturas;
|
||
|
END $$
|
||
|
DELIMITER ;
|
||
|
```
|
||
|
|
||
|
```sql
|
||
|
SELECT f_cantidad_facturas('2018-01-01');
|
||
|
+-----------------------------------+
|
||
|
| f_cantidad_facturas('2018-01-01') |
|
||
|
+-----------------------------------+
|
||
|
| 87 |
|
||
|
+-----------------------------------+
|
||
|
```
|