CodeGym /Cursos /SQL SELF /Operadores RAISE NOTICE, RETURN QUERY

Operadores RAISE NOTICE, RETURN QUERY

SQL SELF
Nivel 50 , Lección 3
Disponible

En programación hay dos cosas clave: entender qué está pasando (sobre todo cuando todo va al revés de lo que planeaste) y devolver datos útiles. Esto es especialmente cierto en PL/pgSQL, porque todo ocurre del lado del servidor, así que hacer debug no siempre es fácil. Por suerte, hay herramientas integradas que ayudan:

RAISE NOTICE — es una forma de mostrar mensajes mientras se ejecuta una función. Piénsalo como un console.log en JavaScript o un print en Python. Puedes mostrar valores de variables, el estado actual de la ejecución o simplemente dejar un "saludo" para tu yo del futuro.

RETURN QUERY — es una forma de devolver un conjunto de datos, como una tabla entera o el resultado de una consulta compleja. Gracias a esto, las funciones PL/pgSQL se parecen mucho a las consultas SQL normales.

Comando RAISE NOTICE

RAISE NOTICE te permite mostrar mensajes en pantalla mientras se ejecuta la función. El formato es así:

RAISE NOTICE 'Mensaje: %', valor;
  • % — es un placeholder para una variable, parecido a printf en C.
  • Después del texto del mensaje puedes poner las variables que quieras mostrar.

Ejemplo de uso

Imagina que escribes una función que cuenta cuántos estudiantes hay en diferentes grupos. Quieres ver los valores intermedios para comprobar que todo va bien.

CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
    group_name TEXT;
    student_count INT;
BEGIN
    FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
        SELECT COUNT(*) INTO student_count
        FROM students WHERE group_name = group_name;

        -- Mostrar resultados
        RAISE NOTICE 'Grupo: %, Cantidad de estudiantes: %', group_name, student_count;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

Cuando llames a esta función:

SELECT count_students_in_groups();

Vas a ver mensajes como estos en los logs:

NOTICE:  Grupo: Matemáticas, Cantidad de estudiantes: 30
NOTICE:  Grupo: Filosofía, Cantidad de estudiantes: 25
NOTICE:  Grupo: Biología, Cantidad de estudiantes: 18

Fíjate que la función no devuelve nada (se crea con RETURNS VOID), pero RAISE NOTICE nos muestra cómo va el ciclo.

Trucos útiles con RAISE

Además de NOTICE, puedes usar otros niveles de mensajes:

  • RAISE DEBUG — para info extra (solo se muestra si el nivel de logs está en DEBUG).
  • RAISE INFO — para información general.
  • RAISE WARNING — para advertencias.
  • RAISE EXCEPTION — para lanzar errores, lo veremos más adelante.

Para debug, lo mejor es usar NOTICE o DEBUG, porque son cómodos y no paran la función.

Comando RETURN QUERY: devuelve datos como un pro

RETURN QUERY se usa en PL/pgSQL para devolver un conjunto de filas. Así puedes devolver el resultado de una consulta SQL directamente desde la función. El formato es:

RETURN QUERY <consulta SQL>;

También puedes combinar varias consultas:

RETURN QUERY <consulta SQL 1>;
RETURN QUERY <consulta SQL 2>;

Ejemplo 1: función con RETURN QUERY

Vamos a escribir una función que devuelve la lista de estudiantes de un grupo dado.

CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT id, name 
    FROM students
    WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;

Ahora llamamos a la función:

SELECT * FROM get_students_by_group('Matemáticas');

Para probar la función, primero crea la tabla students y mete algunos datos:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);

INSERT INTO students (name, group_name) VALUES
('Otto Song',     'Física'),
('Alex Lin',      'Matemáticas'),
('Anna Vel',      'Matemáticas'),
('Maria Chi',     'Historia');

Resultado:

id name
2 Alex Lin
3 Anna Vel

Como ves, la función funciona igual que una consulta SQL normal.

Ejemplo 2: Combinando varias consultas

¿Y si queremos devolver datos combinados de varias tablas? Vamos a devolver la lista de estudiantes y los cursos en los que están inscritos.

CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT s.name, c.name
    FROM students s
    JOIN enrollments e ON s.id = e.student_id
    JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;

Primero crea tres tablas: students, courses y enrollments, y mete algunos datos:

-- Tabla de estudiantes
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- Tabla de cursos
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- Tabla de inscripciones (relación)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);

-- Añadir estudiantes
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

-- Añadir cursos
INSERT INTO courses (name) VALUES
('Matemáticas'),
('Física'),
('Historia');

-- Añadir inscripciones
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> Física
(2, 1), -- Alex -> Matemáticas
(3, 1), -- Anna -> Matemáticas
(4, 3); -- Maria -> Historia

En este caso, al llamar a la función:

SELECT * FROM get_students_and_courses();

vas a obtener este resultado:

student_name course_name
Otto Song Física
Alex Lin Matemáticas
Anna Vel Matemáticas
Maria Chi Historia

La función junta los datos de tres tablas y muestra en qué curso está cada estudiante.

Combinando RAISE NOTICE y RETURN QUERY

A veces RETURN QUERY y RAISE NOTICE pueden ir juntos en una función, así puedes controlar la ejecución y ver resultados intermedios.

Aquí tienes un ejemplo de función que devuelve datos de estudiantes y al mismo tiempo muestra mensajes para ver el progreso:

CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
    count_students INT;
BEGIN
    -- Contar estudiantes
    SELECT COUNT(*) INTO count_students FROM students;
    RAISE NOTICE 'Total de estudiantes: %', count_students;

    -- Devolver datos de estudiantes
    RETURN QUERY
    SELECT id, name FROM students;

    RAISE NOTICE 'La función ha terminado.';
END;
$$ LANGUAGE plpgsql;

Si la tabla students aún no existe, créala y mete algunos datos:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

Ahora, al llamar a la función:

SELECT * FROM debug_students();

Vas a ver tanto los datos como los mensajes:

student_id student_name
1 Otto Song
2 Alex Lin
3 Anna Vel
4 Maria Chi

Salida de mensajes en consola:

NOTICE:  Total de estudiantes: 4
NOTICE:  La función ha terminado.

Errores típicos al usar estas funciones

Error con variables en RAISE NOTICE: si te olvidas de declarar una variable o te equivocas en el nombre, te saldrá el error variable does not exist. Siempre revisa que las variables estén bien declaradas.

Error con el tipo de retorno: si usas RETURN QUERY pero no pones RETURNS TABLE al crear la función, PostgreSQL dará error. Asegúrate de que los tipos de retorno coincidan con los datos que devuelves.

Error con los placeholders en RAISE: si el número de % no coincide con el número de variables, tendrás un error. Por ejemplo:

RAISE NOTICE 'Valor: %, %', valor1;

Esto dará error porque falta la segunda variable.

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