sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Son las consultas de tipo SELECT el único tipo que se puede anidar?

Respuesta básica

Hay CTE (Expresiones de tabla comunes) en Postgres (como en cualquier RDBMS moderno importante excepto MySQL). Desde la versión 9.1 que incluye CTE modificadores de datos. Esos se pueden "anidar".
Actualización:MySQL 8.0 finalmente agrega CTE.

A diferencia de las subconsultas Los CTE se presentan como barreras de optimización. El planificador de consultas no puede incluir comandos triviales en el comando principal ni reordenar combinaciones entre la consulta principal y CTE. Lo mismo es posible con las subconsultas. Puede ser (muy) bueno o (muy) malo para el rendimiento, depende.
De cualquier manera, los CTE requieren un poco más de gastos generales (costo de rendimiento) que las subconsultas.
Actualización:Postgres 12 finalmente puede incorporar CTE sencillos en la consulta principal.

Detalles que no pediste

Su pregunta es muy básica, lo anterior probablemente sea suficiente para responder. Pero agregaré un poco para usuarios avanzados (y un ejemplo de código para mostrar la sintaxis).

Todos los CTE de una consulta se basan en la misma instantánea de la base de datos El próximo CTE puede reutilizar la salida de CTE anteriores (tablas temporales internas), pero los efectos en las tablas subyacentes son invisibles para otros CTE. La secuencia de múltiples CTE es arbitraria a menos que se devuelve algo con RETURNING cláusula para INSERT , UPDATE , DELETE - irrelevante para SELECT , ya que no cambia nada y solo lee desde la instantánea.

Eso puede tener efectos sutiles con múltiples actualizaciones que afectarían a la misma fila. Solo uno la actualización puede afectar a cada fila. Cuál está influenciado por la secuencia de CTE.

Intenta predecir el resultado:

CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');

WITH sel AS (SELECT * FROM t)
   , up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
   , up2 AS (UPDATE t SET txt = t.txt || '2'
             FROM   up1
             WHERE  up1.t_id = t.t_id
             RETURNING t.*)
   , ins AS (INSERT INTO t VALUES (4, 'bamm'))
   , up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't'   AS source, * FROM t;

Violín SQL

No te decepciones, dudo que haya muchos aquí que podrían haberlo hecho. :)
La esencia de esto:evitar Comandos en conflicto en CTE.