CREATE FUNCTION
CREATE FUNCTION define una función almacenada que devuelve un valor. A diferencia de los procedimientos, las funciones se pueden usar directamente en sentencias SQL como SELECT, WHERE y ORDER BY.
Sintaxis
DELIMITER //
CREATE FUNCTION nombre_funcion(parametros)
RETURNS tipo_dato
[DETERMINISTIC | NOT DETERMINISTIC]
[READS SQL DATA | MODIFIES SQL DATA | NO SQL | CONTAINS SQL]
BEGIN
-- Cuerpo de la función
RETURN valor;
END //
DELIMITER ;Ejemplo básico
DELIMITER //
CREATE FUNCTION fn_precio_con_iva(precio DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
RETURN ROUND(precio * 1.21, 2);
END //
DELIMITER ;-- Usar en SELECT
SELECT nombre, precio, fn_precio_con_iva(precio) AS precio_iva
FROM productos
WHERE categoria_id = 6;| nombre | precio | precio_iva |
|---|---|---|
| iPhone 15 Pro | 1299.99 | 1572.99 |
| Samsung Galaxy S24 | 899.99 | 1088.99 |
| Google Pixel 8 | 699.00 | 845.79 |
| Xiaomi 14 | 599.99 | 725.99 |
Parámetros
Los parámetros de las funciones son siempre de tipo IN. No se pueden declarar como OUT o INOUT:
DELIMITER //
CREATE FUNCTION fn_descuento(precio DECIMAL(10,2), porcentaje INT)
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
RETURN ROUND(precio * (1 - porcentaje / 100.0), 2);
END //
DELIMITER ;SELECT nombre, precio,
fn_descuento(precio, 10) AS con_10_pct,
fn_descuento(precio, 20) AS con_20_pct
FROM productos
WHERE precio > 1000;| nombre | precio | con_10_pct | con_20_pct |
|---|---|---|---|
| iPhone 15 Pro | 1299.99 | 1169.99 | 1039.99 |
| MacBook Air M3 | 1399.00 | 1259.10 | 1119.20 |
| Lenovo ThinkPad X1 | 1549.00 | 1394.10 | 1239.20 |
| ASUS ROG Zephyrus | 1899.99 | 1709.99 | 1519.99 |
DETERMINISTIC vs NOT DETERMINISTIC
| Característica | DETERMINISTIC | NOT DETERMINISTIC |
|---|---|---|
| Mismo resultado para mismos parámetros | Sí | No necesariamente |
| Ejemplo | Cálculos matemáticos | Funciones con NOW, RAND |
| Optimización | MySQL puede cachear resultados | No cachea |
-- DETERMINISTIC: siempre devuelve lo mismo
CREATE FUNCTION fn_area_circulo(radio DECIMAL(10,2))
RETURNS DECIMAL(10,4)
DETERMINISTIC
BEGIN
RETURN PI() * radio * radio;
END;
-- NOT DETERMINISTIC: puede variar
DELIMITER //
CREATE FUNCTION fn_dias_desde_pedido(fecha_pedido DATE)
RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
RETURN DATEDIFF(CURDATE(), fecha_pedido);
END //
DELIMITER ;Funciones que leen datos
DELIMITER //
CREATE FUNCTION fn_nombre_categoria(cat_id INT)
RETURNS VARCHAR(50)
READS SQL DATA
BEGIN
DECLARE v_nombre VARCHAR(50);
SELECT nombre INTO v_nombre
FROM categorias WHERE id = cat_id;
RETURN COALESCE(v_nombre, 'Sin categoría');
END //
DELIMITER ;SELECT nombre, precio, fn_nombre_categoria(categoria_id) AS categoria
FROM productos
LIMIT 5;| nombre | precio | categoria |
|---|---|---|
| iPhone 15 Pro | 1299.99 | Electrónica |
| Samsung Galaxy S24 | 899.99 | Electrónica |
| Google Pixel 8 | 699.00 | Electrónica |
| Xiaomi 14 | 599.99 | Electrónica |
| MacBook Air M3 | 1399.00 | Informática |
Función con lógica condicional
DELIMITER //
CREATE FUNCTION fn_nivel_stock(stock INT)
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
IF stock = 0 THEN
RETURN 'Agotado';
ELSEIF stock < 20 THEN
RETURN 'Bajo';
ELSEIF stock < 50 THEN
RETURN 'Normal';
ELSEIF stock < 100 THEN
RETURN 'Alto';
ELSE
RETURN 'Sobrestock';
END IF;
END //
DELIMITER ;SELECT nombre, stock, fn_nivel_stock(stock) AS nivel
FROM productos
WHERE activo = TRUE
ORDER BY stock
LIMIT 8;| nombre | stock | nivel |
|---|---|---|
| Sofá 3 plazas | 8 | Bajo |
| ASUS ROG Zephyrus | 12 | Bajo |
| Lenovo ThinkPad X1 | 18 | Bajo |
| Samsung TV QLED 55" | 20 | Normal |
| MacBook Air M3 | 25 | Normal |
| Google Pixel 8 | 38 | Normal |
| iPhone 15 Pro | 45 | Normal |
| Samsung Galaxy S24 | 62 | Alto |
Usar funciones en WHERE y ORDER BY
-- Filtrar por nivel de stock
SELECT nombre, stock, fn_nivel_stock(stock) AS nivel
FROM productos
WHERE fn_nivel_stock(stock) = 'Bajo';
-- Ordenar por precio con IVA
SELECT nombre, precio, fn_precio_con_iva(precio) AS con_iva
FROM productos
ORDER BY fn_precio_con_iva(precio) DESC
LIMIT 5;RETURN obligatorio
Toda función debe tener al menos una sentencia RETURN. Si una ruta de ejecución no devuelve valor, MySQL genera un error.
Limpieza
DROP FUNCTION IF EXISTS fn_precio_con_iva;
DROP FUNCTION IF EXISTS fn_descuento;
DROP FUNCTION IF EXISTS fn_area_circulo;
DROP FUNCTION IF EXISTS fn_dias_desde_pedido;
DROP FUNCTION IF EXISTS fn_nombre_categoria;
DROP FUNCTION IF EXISTS fn_nivel_stock;En el siguiente artículo veremos cómo listar las funciones existentes con SHOW FUNCTIONS.
Escrito por Eduardo Lázaro
