Error SQL · CTE y alcance

La CTE no existe en la siguiente consulta: entiende el alcance de WITH

Una CTE se parece a una tabla porque puedes consultarla por nombre, pero no queda creada en la base de datos. Su nombre vive dentro de la sentencia a la que pertenece WITH y desaparece al terminar esa sentencia.

Lectura: 14–18 minEjemplo reproduciblePráctica con pistas

El síntoma: la primera consulta funciona y la segunda no encuentra la CTE

PostgreSQL describe las CTE como tablas temporales que existen solo para una consulta. MySQL define una CTE como un resultado temporal con alcance de una única sentencia. SQLite las describe como vistas temporales que existen durante una sola sentencia SQL.

Por tanto, WITH no crea un objeto persistente que puedas reutilizar en la siguiente sentencia independiente.

Ejemplo: intentar reutilizar el nombre después del punto y coma

Dos sentencias separadas
WITH clientes_activos AS (
  SELECT id, nombre
  FROM clientes
  WHERE activo = 1
)
SELECT *
FROM clientes_activos;

SELECT COUNT(*)
FROM clientes_activos;

La primera sentencia puede usar clientes_activos. Cuando termina en el punto y coma, esa CTE deja de formar parte del alcance. La segunda sentencia necesita definirla de nuevo o consultar otro objeto real.

Si necesitas varios resultados dentro de una sola sentencia, reutiliza la CTE allí

Una misma CTE puede referenciarse varias veces dentro de la sentencia que la contiene. Por ejemplo, puedes compararla consigo misma, usarla en subconsultas o basar otras CTE en ella.

Una sentencia, un mismo alcance
WITH clientes_activos AS (
  SELECT id, nombre
  FROM clientes
  WHERE activo = 1
)
SELECT
  (SELECT COUNT(*) FROM clientes_activos) AS total,
  (SELECT MIN(id) FROM clientes_activos) AS primer_id;

Si necesitas reutilización entre sentencias, elige otro mecanismo

La solución depende de la intención:

  • Repetir la lógica en pocas consultas: vuelve a declarar la CTE.
  • Compartir una consulta estable: considera una vista.
  • Guardar resultados intermedios durante una sesión o proceso: una tabla temporal puede ser más adecuada, con sintaxis y ciclo de vida específicos del motor.
  • Persistir datos: usa una tabla normal si realmente forman parte del modelo.

No conviertas automáticamente una CTE en tabla permanente: primero decide si quieres reutilizar una definición o almacenar datos.

Puedes encadenar varias CTE dentro del mismo WITH

CTE basada en otra CTE
WITH clientes_activos AS (
  SELECT id, nombre
  FROM clientes
  WHERE activo = 1
),
primeros AS (
  SELECT id, nombre
  FROM clientes_activos
  WHERE id <= 100
)
SELECT *
FROM primeros;

Las CTE comparten la sentencia y pueden formar una secuencia legible de transformaciones.

Método de diagnóstico

  1. Busca el punto y coma que termina la sentencia con WITH.
  2. Comprueba si el error aparece después de ese límite.
  3. Decide si necesitas otra consulta o persistencia real.
  4. Si todo pertenece a una única tarea, considera mantenerlo en una sola sentencia con varias CTE.
  5. Si el resultado debe vivir más tiempo, usa una vista o tabla según el caso.

Error frecuente: pensar que WITH equivale a CREATE VIEW

Una CTE nombra un resultado dentro de una sentencia

CREATE VIEW crea un objeto de esquema que puede consultarse más tarde. WITH introduce nombres auxiliares para la sentencia actual. Son herramientas relacionadas en legibilidad, pero tienen ciclos de vida distintos.

Práctica correctiva

Básica · CTE

Obtén dos métricas sin salir del alcance

Define una CTE pedidos_pagados con los pedidos cuyo estado sea 'pagado'. En una sola sentencia devuelve el número de pedidos y el importe máximo.

Qué debes recordar

  • Una CTE tiene alcance de una sola sentencia SQL.
  • El punto y coma marca el final de ese alcance.
  • Puedes referenciar una CTE varias veces dentro de la misma sentencia.
  • Para reutilización posterior, evalúa una vista o una tabla según la necesidad.

Conceptos relacionados

Fuentes técnicas

La sintaxis y las diferencias de motor de esta guía se contrastaron con documentación primaria: