PostgreSQL 19: ON CONFLICT DO SELECT, SQL/PGQ y COPY TO en JSON, con ejemplos

PostgreSQL 19 lleva desde junio en fase beta (Beta 1 el 4 de junio, Beta 2 el 16 de julio de 2026), con lanzamiento estable previsto para septiembre u octubre. No es de las versiones que reinventan el motor, pero trae varias features que se notan en el día a día si escribes SQL con frecuencia. Vamos con ejemplos concretos de las que más juego dan.

ON CONFLICT DO SELECT

Hasta ahora, un UPSERT con ON CONFLICT solo podía terminar en DO NOTHING o DO UPDATE. PostgreSQL 19 añade una tercera vía: DO SELECT, que devuelve la fila existente cuando hay conflicto, sin necesidad de un segundo SELECT ni de un CTE con RETURNING:

INSERT INTO usuarios (email, nombre)
VALUES ('[email protected]', 'Ana')
ON CONFLICT (email) DO SELECT
RETURNING id, email, nombre;

Es el patrón clásico de «obtener o crear» resuelto en una sola sentencia, sin condiciones de carrera entre el SELECT y el INSERT.

SQL/PGQ: consultas de grafos en SQL estándar

PostgreSQL 19 incorpora SQL/PGQ (Property Graph Queries), la extensión del estándar SQL:2023 para consultar datos relacionales como si fueran un grafo. Se define una vista de grafo sobre tablas existentes y se consulta con la cláusula GRAPH_TABLE:

CREATE PROPERTY GRAPH red_social
VERTEX TABLES (usuarios KEY (id) LABEL persona)
EDGE TABLES (
  seguidores
    SOURCE KEY (seguidor_id) REFERENCES usuarios (id)
    DESTINATION KEY (seguido_id) REFERENCES usuarios (id)
    LABEL sigue
);

SELECT nombre_origen, nombre_destino
FROM GRAPH_TABLE (red_social
  MATCH (a IS persona)-[IS sigue]->(b IS persona)
  COLUMNS (a.nombre AS nombre_origen, b.nombre AS nombre_destino)
);

No hace falta montar Neo4j ni ninguna base de datos de grafos aparte para relaciones de este tipo, si los datos ya viven en PostgreSQL y las consultas no son extremadamente profundas.

COPY TO con salida JSON nativa

El comando COPY gana un formato de salida JSON de serie, sin tener que envolver la consulta en row_to_json() ni exportar a CSV para luego convertir:

COPY (SELECT id, nombre, email FROM usuarios WHERE activo)
TO '/tmp/usuarios.json'
WITH (FORMAT json);

Cada fila sale como un objeto JSON independiente, en formato JSON Lines, cómodo para pipelines que ya esperan ese formato de entrada.

FOR PORTION OF: modificar solo un tramo temporal

Con soporte de tablas temporales (PERIOD) ya asentado, PostgreSQL 19 completa el estándar SQL:2011 con FOR PORTION OF, que permite actualizar o borrar solo el tramo de tiempo que corresponde, partiendo automáticamente el resto del periodo:

UPDATE contratos
FOR PORTION OF vigencia FROM '2026-09-01' TO '2026-12-01'
SET tarifa = 45.00
WHERE cliente_id = 102;

Antes de esto, ese mismo cambio requería calcular a mano los tramos anteriores y posteriores al periodo afectado, e insertar filas adicionales para no perder el historial. Ahora lo hace el motor.

REPACK nativo y autovacuum en paralelo

Llega un REPACK nativo para mantenimiento de tablas online, heredero conceptual de la extensión pg_repack pero integrado en el propio motor, sin bloquear la tabla mientras se reorganiza físicamente.

El autovacuum, por su parte, ya puede repartir el trabajo entre varios workers en paralelo, configurable con el nuevo parámetro:

ALTER SYSTEM SET autovacuum_max_parallel_workers = 4;

En tablas grandes con mucha rotación de filas, este cambio por sí solo puede reducir bastante el tiempo que el autovacuum tarda en ponerse al día.

Dos cambios de valores por defecto a tener en cuenta

Dos defaults cambian en esta versión y conviene revisarlos antes de actualizar en producción:

  • JIT desactivado por defecto. La compilación just-in-time de consultas pasa a estar apagada de serie. Si tu carga de trabajo se beneficiaba de ella (consultas analíticas pesadas), hay que reactivarla explícitamente con SET jit = on;.
  • Compresión TOAST con lz4 por defecto. Los valores grandes que PostgreSQL guarda fuera de la fila (TOAST) se comprimen ahora con lz4 en vez de pglz, más rápido a costa de una compresión ligeramente peor.

Ninguno de los dos rompe nada por sí solo, pero sí pueden cambiar el perfil de rendimiento de una aplicación que llevaba tiempo ajustada a los valores anteriores.

Documentación completa en las notas de la versión 19 en postgresql.org.

Relacionado: PostgreSQL vs MySQL para cargas de IA.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP