CodeGym /Cursos /SQL SELF /Interacción entre funciones y procedimientos

Interacción entre funciones y procedimientos

SQL SELF
Nivel 55 , Lección 1
Disponible

Hace un par de niveles ya tocamos el tema de procedimientos y funciones en PostgreSQL. Ahora toca profundizar más.

Las funciones y los procedimientos pueden funcionar por separado, pero normalmente su interacción es lo que define el éxito de todo el sistema. Lo más cómodo es que puedes llamar funciones unas desde otras, pasar datos e incluso obtener el resultado de la ejecución.

Funciones vs Procedimientos: ¿en qué se diferencian?

Vamos a recordar en qué se diferencian las funciones de los procedimientos en PostgreSQL:

  • Funciones (FUNCTION):

    • Devuelven valores.
    • Puedes usarlas en SELECT.
    • Se usan mucho para cálculos o transformación de datos.
  • Procedimientos (PROCEDURE):

    • No devuelven valores directamente.
    • Se usan para operaciones como insertar, actualizar o borrar datos.
    • Se llaman con el comando CALL.

Paso de datos entre funciones

Vamos a la práctica, empezando con un ejemplo básico de cómo pasar datos entre una función y un procedimiento. Básicamente, el paso de datos entre funciones se hace a través de parámetros y valores devueltos.

Así se ve una llamada a una función dentro de otra función:

CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    -- Sacamos el nombre del estudiante por su ID
    SELECT name INTO student_name FROM students WHERE id = student_id;

    -- Devolvemos el nombre
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

Esta función se puede llamar desde otra función:

CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
    message TEXT;
BEGIN
    -- Obtenemos el nombre del estudiante usando otra función
    message := '¡Bienvenido, ' || get_student_name(student_id) || '!';

    -- Devolvemos el saludo
    RETURN message;
END;
$$ LANGUAGE plpgsql;
  1. La función get_student_name devuelve el nombre del estudiante por su identificador (student_id).
  2. En la otra función — welcome_student — ese nombre se usa para crear un mensaje de bienvenida.

Nota: Sacar datos usando SELECT INTO guarda el resultado de la consulta en una variable de PL/pgSQL.

Ejemplo de llamada a procedimientos desde funciones

Ahora vamos a ver cómo llamar un procedimiento desde una función. Imagina que tienes un procedimiento que registra la hora de entrada de un estudiante al sistema:

CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO log_entries(student_id, entry_time)
    VALUES (student_id, NOW());
END;
$$;

Ahora llamamos a este procedimiento desde una función, donde se registra la entrada y se devuelve un mensaje:

CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
    -- Llamamos al procedimiento para registrar el log
    CALL log_student_entry(student_id);

    -- Devolvemos el mensaje
    RETURN 'Inicio de sesión del estudiante registrado correctamente.';
END;
$$ LANGUAGE plpgsql;

Ejemplos prácticos de interacción

Ejemplo 1: cálculo del total del pedido y registro del pedido

Imagina que trabajas con un sistema de pedidos online. Para calcular el total de un pedido tienes una función:

CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Sumamos todas las posiciones del pedido
    SELECT SUM(price * quantity) INTO total
    FROM order_items
    WHERE order_id = order_id;

    RETURN total;
END;
$$ LANGUAGE plpgsql;

Para guardar el total del pedido se usa un procedimiento:

CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO order_totals(order_id, total)
    VALUES (order_id, total);
END;
$$;

Ahora los unimos:

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Llamamos a la función para calcular el total
    total := calculate_order_total(order_id);

    -- Registramos el total usando el procedimiento
    CALL log_order_total(order_id, total);

    RETURN 'Pedido procesado correctamente.';
END;
$$ LANGUAGE plpgsql;

Ejemplo 2: obtener la máxima puntuación del estudiante y actualizar el perfil

Función para obtener la máxima puntuación:

CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Buscamos la máxima puntuación del estudiante
    SELECT MAX(rating) INTO max_rating
    FROM ratings
    WHERE student_id = student_id;

    RETURN max_rating;
END;
$$ LANGUAGE plpgsql;

Procedimiento para actualizar el perfil del estudiante:

CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE students
    SET highest_rating = max_rating
    WHERE id = student_id;
END;
$$;

Función para llamar a estas operaciones:

CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Obtenemos la máxima puntuación
    max_rating := get_highest_rating(student_id);

    -- Actualizamos el perfil del estudiante
    CALL update_student_profile(student_id, max_rating);

    RETURN 'Perfil actualizado correctamente.';
END;
$$ LANGUAGE plpgsql;

Errores típicos en la interacción

Uno de los errores más comunes es la incompatibilidad de tipos de datos entre la función y el procedimiento. Por ejemplo, si tu procedimiento espera un parámetro de tipo NUMERIC y le pasas un INTEGER, PostgreSQL te va a avisar del error de tipos. Siempre revisa que los tipos de datos coincidan.

Otro error es el llamado cíclico de funciones, cuando la función A llama a la función B, y esta a su vez vuelve a llamar a A. Esto lleva a llamadas infinitas y a que el sistema se caiga.

Importancia práctica

¿Para qué nos sirve esta interacción? En la vida real, las funciones y los procedimientos funcionan como "bloques de construcción" de sistemas complejos. Permiten dividir el código en partes independientes, lo que facilita el debug, la reutilización y las pruebas. Por ejemplo:

  • En una entrevista te pueden pedir que escribas una función que llame a un procedimiento para realizar una operación compleja. Demostrar habilidades prácticas de interacción será un gran plus.
  • Al desarrollar aplicaciones reales, como tiendas online, sistemas de logs o CRM, saber organizar bien la funcionalidad a través de la interacción entre funciones y procedimientos simplifica mucho el código.

Para seguir aprendiendo sobre la interacción entre funciones y procedimientos puedes mirar la documentación oficial de PL/pgSQL.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION