Explicación de PL/pgSQL
PL/pgSQL es el lenguaje procedural incorporado de PostgreSQL, y toda su propuesta de valor es que se ejecuta dentro del mismo proceso que el ejecutor de consultas en lugar de enviar filas de un lado a otro a un cliente.
Busca en todas las páginas de la documentación
PL/pgSQL es el lenguaje procedural incorporado de PostgreSQL, y toda su propuesta de valor es que se ejecuta dentro del mismo proceso que el ejecutor de consultas en lugar de enviar filas de un lado a otro a un cliente.
Esa proximidad también es su límite: PL/pgSQL no es un lenguaje de programación de propósito general, es un pegamento para expresar el flujo de control que el SQL plano no puede, y recurrir a él demasiado pronto renuncia a la capacidad del planificador para optimizar tu lógica como una sola consulta.
Esta página construye el modelo mental detrás de los bloques, la volatilidad, STRICT y la división función-versus-procedimiento para que Conceptos básicos de funciones, Fundamentos de PL/pgSQL, Volatilidad y STRICT y Procedimientos almacenados y CALL se lean como un sistema coherente.
DECLARE/BEGIN/EXCEPTION/END) alrededor de sentencias SQL, ejecutándose dentro del proceso de la base de datos en lugar de hacer viajes de ida y vuelta a un cliente.El cuerpo de una función PL/pgSQL es un bloque: una sección opcional DECLARE para variables locales, una sección BEGIN/END que contiene sentencias, y una sección opcional EXCEPTION para el manejo de errores.
CREATE OR REPLACE FUNCTION app.bump_version(p_id bigint)
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
UPDATE app.accounts SET name = name || ' v2' WHERE id = p_id;
IF NOT FOUND THEN
RAISE EXCEPTION 'missing account %', p_id;
END IF;
END;
$$;Cada sentencia SQL dentro de ese bloque se ejecuta a través de la Interfaz de Programación del Servidor (SPI) de PostgreSQL, la misma API interna que permite a PL/pgSQL entregar una cadena de consulta al analizador, planificador y ejecutor ordinarios y obtener filas de vuelta.
La variable especial FOUND se establece después de cada sentencia ejecutada por SPI para indicar si afectó o devolvió al menos una fila, que es exactamente lo que el ejemplo anterior utiliza para detectar una cuenta faltante.
El flujo de control se lee como cualquier lenguaje procedural: IF/ELSIF/ELSE, LOOP/WHILE/FOR, y un cursor implícito se abre automáticamente cada vez que un bucle FOR itera sobre los resultados de una consulta.
El modelo mental más simple es que PL/pgSQL es una capa de scripting delgada envuelta alrededor de sentencias SQL ordinarias, no un reemplazo para la lógica basada en conjuntos propia de SQL.
Una función (CREATE FUNCTION) siempre se ejecuta dentro de la transacción que la llamó y devuelve un valor con RETURN, mientras que un procedimiento (CREATE PROCEDURE, invocado con CALL) puede emitir su propio COMMIT o ROLLBACK y no devuelve nada a menos que utilice parámetros OUT.
Esa división en el control de transacciones existe porque una función puede ser llamada desde dentro de una expresión SQL más grande, como una lista SELECT o una cláusula WHERE, donde iniciar o finalizar una transacción a mitad de sentencia no tendría sentido.
La volatilidad le dice al planificador lo que puede asumir sobre las llamadas repetidas: IMMUTABLE promete que la misma entrada siempre produce la misma salida sin efectos secundarios, STABLE promete el mismo resultado dentro de la instantánea de una sola sentencia, y VOLATILE (el valor predeterminado) no promete nada y fuerza una nueva llamada cada vez.
IMMUTABLE -> puede ser plegado a constante, indexado en un índice de expresión
STABLE -> seguro para llamar una vez por sentencia, reutilizado entre filas
VOLATILE -> re-evaluado para cada fila, bloquea muchas optimizacionesMarcar una función como STRICT le dice a PostgreSQL que si algún argumento es NULL, la función debe devolver NULL inmediatamente sin ejecutar el cuerpo, lo que ahorra trabajo y elimina una clase de errores de manejo de NULL de la propia función.
Las funciones de trigger son un caso especial que devuelve el pseudo-tipo trigger en lugar de un tipo SQL normal, y PostgreSQL las llama automáticamente con variables de fila implícitas NEW/OLD en lugar de argumentos explícitos, que es la maquinaria compartida detrás de El Modelo de Triggers.
El manejo de excepciones funciona a través de la cláusula EXCEPTION WHEN, y dado que PostgreSQL lo implementa con un punto de salvaguarda internamente, capturar un error dentro de un bucle grande tiene un costo real por iteración que un trabajo por lotes bien diseñado debería tener en cuenta.
SECURITY DEFINER cambia con qué privilegios se ejecuta una función: por defecto, una función se ejecuta como SECURITY INVOKER (los privilegios del usuario que llama), mientras que SECURITY DEFINER la hace ejecutarse como el propietario de la función, que es cómo se permite a un usuario de bajo privilegio realizar una acción privilegiada de alcance limitado sin otorgarle acceso amplio a tablas.
Ese poder viene con una trampa bien conocida: una función SECURITY DEFINER que no fija su propio search_path puede ser engañada para resolver un nombre no calificado a un objeto malicioso que el llamador controla, razón por la cual cada función SECURITY DEFINER debe establecer explícitamente search_path en su definición.
La volatilidad también afecta la elegibilidad para consultas paralelas, ya que una función VOLATILE deshabilita el paralelismo para la consulta que la llama a menos que también esté marcada como PARALLEL SAFE, por lo que una función que parece inofensiva puede forzar silenciosamente un plan serial en una consulta que de otro modo sería paralelizable.
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
| Función SQL | Se inserta en la consulta que la llama, totalmente optimizable por el planificador | Ningún flujo de control procedural en absoluto | Envolturas simples, columnas calculadas, expresiones reutilizables pequeñas |
| Función PL/pgSQL | Control procedural, manejo de excepciones, invocable desde expresiones SQL | No puede gestionar sus propias transacciones | Lógica de varios pasos invocada desde una consulta u otra función |
Procedimiento (CALL) | Puede hacer COMMIT/ROLLBACK a mitad de ejecución | No se puede llamar desde dentro de una expresión SQL | Trabajos por lotes largos que necesitan commits periódicos |
| Función de trigger | Se ejecuta automáticamente en DML, ve NEW/OLD | Añade costo invisible a cada escritura en la tabla | Aplicación de invariantes o captura de cambios en el momento de la escritura |
Probar funciones de base de datos merece la misma disciplina que probar código de aplicación, y dado que las funciones PL/pgSQL se ejecutan dentro de una transacción por defecto, envolver una prueba en una transacción que siempre se revierte es una forma barata de ejercitar los efectos secundarios reales de una función sin dejar datos de prueba en la base de datos.
CALL puede emitir su propio COMMIT o ROLLBACK, una función siempre se ejecuta dentro de la transacción del llamador.STRICT significa que si algún argumento es NULL, la función devuelve NULL inmediatamente sin ejecutar su cuerpo, no dice nada sobre si el llamador puede omitir el argumento.search_path no fijado aún puede permitir a un llamador escalar lo que hace la función.VOLATILE cuando en realidad es determinista deshabilita el plegado de constantes, los índices de expresiones y la elegibilidad de consultas paralelas que IMMUTABLE o STABLE habrían desbloqueado.Un solo bloque: una sección opcional DECLARE para variables locales, una sección BEGIN/END de sentencias, y una sección opcional EXCEPTION para el manejo de errores.
Cada sentencia SQL incrustada se entrega a la Interfaz de Programación del Servidor (SPI), que la dirige a través del mismo analizador, planificador y ejecutor que cualquier consulta ejecutada desde un cliente.
Refleja si la sentencia ejecutada más recientemente por SPI afectó o devolvió al menos una fila, que es la forma estándar de verificar si una UPDATE o SELECT INTO realmente coincidió con algo.
No, solo un procedimiento invocado con CALL puede emitir COMMIT o ROLLBACK; una función siempre se ejecuta dentro de la transacción que la llamó.
CALL en lugar de incrustarlo en una consulta.Si algún argumento es NULL, PostgreSQL devuelve NULL inmediatamente sin ejecutar nunca el cuerpo de la función, lo que ahorra trabajo y elimina una clase de errores de manejo de NULL.
Una función STABLE tiene garantizado que devolverá el mismo resultado para los mismos argumentos dentro de la instantánea de una sentencia, permitiendo al planificador llamarla una vez y reutilizar el resultado, mientras que una función VOLATILE debe ser llamada de nuevo para cada fila.
Sí, las funciones IMMUTABLE pueden respaldar un índice de expresión, y las funciones VOLATILE deshabilitan las consultas paralelas para la sentencia que las llama a menos que también estén marcadas como PARALLEL SAFE.
Si la función no fija su propio search_path, un llamador puede manipular el search_path de su sesión para engañar a la función y hacer que resuelva un nombre no calificado a un objeto que el llamador controla.
Devuelve el pseudo-tipo especial trigger, nunca se llama directamente con argumentos y, en cambio, recibe variables de fila implícitas NEW/OLD cuando PostgreSQL la invoca automáticamente en un evento DML coincidente.
Cada bloque EXCEPTION WHEN se implementa con un punto de salvaguarda subyacente, por lo que envolver el manejo de errores alrededor de cada iteración de un bucle grande añade un costo real por iteración que vale la pena medir en trabajos por lotes.
Prefiera SQL plano siempre que la lógica sea genuinamente basada en conjuntos, y recurra a PL/pgSQL solo cuando necesite ramificación real, bucles o manejo de excepciones que una sola consulta no pueda expresar.
Envuelva la llamada de prueba en una transacción que siempre se revierte al final, lo que ejercita los efectos secundarios reales de la función sin dejar datos de prueba en la base de datos.
FOUND en la prácticaIMMUTABLE/STABLE/VOLATILE y efectos en el planificadorsearch_pathCALLVersiones de Stack: Esta página fue escrita para PostgreSQL 18.4 (línea estable 18, línea de mantenimiento 17), donde la estructura de bloques, la volatilidad,
STRICTy el comportamiento deSECURITY DEFINERdescritos aquí han sido estables en las versiones principales recientes.
Revisado por Chris St. John·Última actualización: 15 jul 2026