CodeGym /Cursos /SQL SELF /Análisis de errores típicos al crear funciones

Análisis de errores típicos al crear funciones

SQL SELF
Nivel 50 , Lección 4
Disponible

Hoy vamos a analizar los errores típicos al crear funciones, sus causas y cómo solucionarlos. Porque solo depurando es como un verdadero crack aprende su oficio: ¡el coding! ¡Vamos a debuggear!

Crear funciones, sobre todo cuando empiezas con PL/pgSQL, puede parecer complicado. Incluso los devs más experimentados en PostgreSQL se topan con trampas. Vamos a verlas una por una.

1. Olvidar la palabra clave RETURNS

PL/pgSQL es muy estricto con cómo describes las funciones. Uno de los errores más comunes es olvidarse de indicar el tipo de dato que debe devolver la función. Mira este ejemplo:

-- Error: falta la palabra clave RETURNS
CREATE FUNCTION incorrect_function() AS $$
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

PostgreSQL no puede entender qué debe devolver esta función. RETURNS es obligatorio y describe el tipo de dato que se devuelve (por ejemplo, RETURNS INT, RETURNS TEXT o incluso RETURNS VOID).

Solución: añade la palabra clave RETURNS con el tipo de dato:

CREATE FUNCTION correct_function() RETURNS INT AS $$
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

2. Devolver un resultado sin RETURN

Los que empiezan suelen olvidar que en PL/pgSQL, para devolver un resultado, hay que usar explícitamente el operador RETURN. Por ejemplo:

-- Error: falta RETURN
CREATE FUNCTION missing_return() RETURNS TEXT AS $$
BEGIN
    '¡Hola, Mundo!'; -- Solo una cadena, pero no devuelta
END;
$$ LANGUAGE plpgsql;

Aquí la cadena '¡Hola, Mundo!' solo está escrita, pero no se devuelve. PostgreSQL lo interpreta como un resultado no alcanzado y lanza un error.

Solución: añade el operador RETURN explícitamente:

CREATE FUNCTION fixed_return() RETURNS TEXT AS $$
BEGIN
    RETURN '¡Hola, Mundo!';
END;
$$ LANGUAGE plpgsql;

3. Intentar asignar datos a una variable no declarada

En PL/pgSQL tienes que declarar la variable en el bloque DECLARE antes de usarla. Por ejemplo:

-- Error: la variable my_var no está declarada
CREATE FUNCTION missing_variable() RETURNS VOID AS $$
BEGIN
    my_var := '¡Hola, Mundo!';
END;
$$ LANGUAGE plpgsql;

PostgreSQL no sabe que existe la variable my_var porque no la declaraste en el bloque DECLARE.

Solución: declara siempre las variables en DECLARE:

CREATE FUNCTION declared_variable() RETURNS VOID AS $$
DECLARE
    my_var TEXT;
BEGIN
    my_var := '¡Hola, Mundo!';
END;
$$ LANGUAGE plpgsql;

4. Uso incorrecto del tipo de retorno VOID

El tipo VOID indica que la función no devuelve ningún dato. A veces los devs intentan usar RETURN en funciones con tipo VOID, lo que da error:

-- Error: RETURN en función con VOID
CREATE FUNCTION void_example() RETURNS VOID AS $$
BEGIN
    RETURN 1; -- No se puede devolver un valor
END;
$$ LANGUAGE plpgsql;

Las funciones con tipo de retorno VOID no deben devolver valores. Puedes usar RETURN, pero sin valor.

Solución: o bien quita RETURN, o ponlo sin valor:

CREATE FUNCTION correct_void() RETURNS VOID AS $$
BEGIN
    -- Solo hacemos acciones
    RAISE NOTICE 'Esta función no devuelve nada';
    RETURN; -- Fin de la función
END;
$$ LANGUAGE plpgsql;

5. Uso incorrecto de RAISE para debuggear

Para depurar en PL/pgSQL se usa mucho RAISE NOTICE. Pero si usas formatos o variables mal, tendrás errores.

Ejemplo:

-- Error: formato incorrecto
CREATE FUNCTION debug_example() RETURNS VOID AS $$
BEGIN
    RAISE NOTICE 'El valor es %'; -- Falta la variable
END;
$$ LANGUAGE plpgsql;

El operador RAISE espera que después de % venga una variable o valor. Si dejas % solo, PostgreSQL no puede procesar el comando.

Solución: asegúrate de poner las variables o valores correctamente:

CREATE FUNCTION fixed_debug() RETURNS VOID AS $$
DECLARE
    my_var TEXT := 'PostgreSQL';
BEGIN
    RAISE NOTICE 'El valor es %', my_var; -- Variable puesta
END;
$$ LANGUAGE plpgsql;

6. Problemas con nombres de variables y columnas

Si el nombre de una variable coincide con el de una columna, puede haber resultados raros. Por ejemplo:

-- Error: conflicto de nombres entre variable y columna
CREATE FUNCTION name_conflict() RETURNS TEXT AS $$
DECLARE
    name TEXT;
BEGIN
    SELECT name INTO name FROM students LIMIT 1; -- ¿Qué name se usa?
    RETURN name;
END;
$$ LANGUAGE plpgsql;

PL/pgSQL da preferencia a las variables si hay coincidencia de nombres.

Solución: usa alias para las tablas o evita coincidencias.

CREATE FUNCTION fixed_conflict() RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    SELECT s.name INTO student_name FROM students s LIMIT 1;
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

7. Ejecución incorrecta de consultas en bucles

Los errores suelen pasar al intentar ejecutar consultas SQL dentro de bucles. Por ejemplo:

-- Error: consulta incorrecta dentro del bucle
CREATE FUNCTION cycle_error() RETURNS VOID AS $$
BEGIN
    FOR rec IN SELECT * FROM students LOOP
        EXECUTE 'UPDATE students SET active = TRUE WHERE id = ' || rec.id;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

SQL-inyecciones... ¡Peligro! Concatenar strings para consultas SQL es mala práctica. Puede ser vulnerable.

Para arreglarlo, usa parámetros:

CREATE FUNCTION safe_cycle() RETURNS VOID AS $$
BEGIN
    FOR rec IN SELECT * FROM students LOOP
        EXECUTE 'UPDATE students SET active = TRUE WHERE id = $1' USING rec.id;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

8. Errores con tipos de datos

Ejemplo de error:

-- Error: tipos de datos no coinciden
CREATE FUNCTION type_error() RETURNS INT AS $$
DECLARE
    my_var TEXT := 'no_es_un_numero';
BEGIN
    RETURN my_var; -- Error al devolver texto en vez de INT
END;
$$ LANGUAGE plpgsql;

PostgreSQL espera INT, pero recibe TEXT. La coincidencia de tipos de datos se controla estrictamente.

¿Cómo arreglarlo? Asegúrate de que los tipos coincidan, o haz una conversión explícita:

CREATE FUNCTION type_correct() RETURNS INT AS $$
DECLARE
    my_var TEXT := '42';
BEGIN
    RETURN my_var::INT; -- Convertir texto a número
END;
$$ LANGUAGE plpgsql;

Mejores prácticas y consejos

  • Divide funciones complejas en otras más pequeñas. Así es más fácil debuggear y testear.
  • Usa comentarios dentro de las funciones para explicar operaciones complejas.
  • Prueba siempre las funciones con pocos datos antes de usarlas en tablas reales.
  • Depura usando RAISE NOTICE para entender el flujo de ejecución.
  • Evita SQL-inyecciones: usa parámetros en las consultas.
-- Uso de RAISE para debuggear
DO $$
DECLARE
    total_students INT;
BEGIN
    SELECT COUNT(*) INTO total_students FROM students;
    RAISE NOTICE 'Total de estudiantes: %', total_students; -- Mensaje de depuración
END;
$$;

¡Estos consejos te van a ahorrar muchos dolores de cabeza y te ayudarán a esquivar para siempre las "trampas" de PL/pgSQL!

1
Cuestionario/control
Creación de funciones simples, nivel 50, lección 4
No disponible
Creación de funciones simples
Creación de funciones simples
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION