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;
nombreprecioprecio_iva
iPhone 15 Pro1299.991572.99
Samsung Galaxy S24899.991088.99
Google Pixel 8699.00845.79
Xiaomi 14599.99725.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;
nombrepreciocon_10_pctcon_20_pct
iPhone 15 Pro1299.991169.991039.99
MacBook Air M31399.001259.101119.20
Lenovo ThinkPad X11549.001394.101239.20
ASUS ROG Zephyrus1899.991709.991519.99

DETERMINISTIC vs NOT DETERMINISTIC

CaracterísticaDETERMINISTICNOT DETERMINISTIC
Mismo resultado para mismos parámetrosNo necesariamente
EjemploCálculos matemáticosFunciones con NOW, RAND
OptimizaciónMySQL puede cachear resultadosNo 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;
nombrepreciocategoria
iPhone 15 Pro1299.99Electrónica
Samsung Galaxy S24899.99Electrónica
Google Pixel 8699.00Electrónica
Xiaomi 14599.99Electrónica
MacBook Air M31399.00Informá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;
nombrestocknivel
Sofá 3 plazas8Bajo
ASUS ROG Zephyrus12Bajo
Lenovo ThinkPad X118Bajo
Samsung TV QLED 55"20Normal
MacBook Air M325Normal
Google Pixel 838Normal
iPhone 15 Pro45Normal
Samsung Galaxy S2462Alto

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