Modificar datos · salida de la sentencia

RETURNING con INSERT, UPDATE y DELETE

Recupera IDs generados y valores de las filas modificadas desde la misma sentencia, sin confundir una extensión del motor con SQL portable.

Lectura: 9–11 minEjemplos comprobadosPráctica con pistas
Contenido de esta guía

Respuesta rápida

RETURNING permite que una sentencia que modifica datos devuelva columnas de las filas afectadas sin lanzar un SELECT adicional. Es especialmente útil para recuperar un identificador generado, comprobar los nuevos valores de un UPDATE o saber qué fila eliminó un DELETE.

Patrón
INSERT INTO pedidos (cliente, estado)
VALUES ('Ana', 'pendiente')
RETURNING id, cliente, estado;

No lo trates como SQL universal. PostgreSQL y SQLite lo documentan, pero RETURNING es una extensión y su alcance cambia entre motores.

¿Para qué sirve RETURNING?

Una modificación de datos puede producir información que la aplicación necesita inmediatamente. Por ejemplo, una clave autogenerada no existía antes del INSERT, y un UPDATE puede calcular el nuevo valor a partir del anterior. RETURNING convierte esa información en el resultado de la misma sentencia.

Qué puede devolverte RETURNING
SentenciaUso habitualValor que interesa
INSERTCrear una filaID, DEFAULT u otros valores calculados
UPDATEModificar filasValores resultantes después del cambio
DELETEEliminar filasDatos de las filas que se acaban de eliminar

En PostgreSQL, la lista de RETURNING funciona de forma parecida a la lista de salida de un SELECT: puedes devolver columnas o expresiones. SQLite también permite una lista de expresiones y RETURNING * para las columnas de la tabla modificada.

INSERT ... RETURNING: recuperar el ID generado

Este ejemplo usa una clave entera generada por SQLite. El mismo patrón es habitual en PostgreSQL cuando el identificador proviene de una identidad, secuencia o valor por defecto.

SQL comprobado en SQLite
CREATE TEMP TABLE pedidos_returning (
  id INTEGER PRIMARY KEY,
  cliente TEXT NOT NULL,
  estado TEXT NOT NULL DEFAULT 'pendiente'
);

INSERT INTO pedidos_returning (cliente)
VALUES ('Ana')
RETURNING id, cliente, estado;
Resultado comprobado
idclienteestado
1Anapendiente

El valor pendiente procede del DEFAULT y el id lo asigna la tabla. No hace falta adivinar esos valores ni repetir una búsqueda para recuperarlos.

UPDATE y DELETE con RETURNING

Con UPDATE, las referencias normales a las columnas representan el estado posterior a la modificación. Con DELETE, representan los datos de la fila que se elimina.

Actualizar y devolver
UPDATE pedidos_returning
SET estado = 'enviado'
WHERE id = 1
RETURNING id, estado;
Resultado del UPDATE
idestado
1enviado
Eliminar y devolver
DELETE FROM pedidos_returning
WHERE id = 1
RETURNING id, cliente, estado;
Fila devuelta antes de desaparecer de la tabla
idclienteestado
1Anaenviado

Mejor columnas explícitas que RETURNING *

RETURNING * resulta cómodo al explorar, pero en código estable suele ser mejor pedir solo los datos que necesitas. Así el resultado tiene un contrato más pequeño y no cambia innecesariamente si la tabla incorpora columnas nuevas.

Salida explícita
INSERT INTO pedidos (cliente_id, estado)
VALUES (7, 'pendiente')
RETURNING id, estado;

RETURNING no sustituye a SELECT

RETURNING responde a una pregunta muy concreta: «¿qué valores produjo esta modificación?». Un SELECT sigue siendo la herramienta para consultar el estado general de una tabla, unirla con otras o recuperar información en otro momento.

Regla mental: usa RETURNING para obtener el resultado inmediato del cambio; usa SELECT para consultar datos como una operación independiente.

Errores frecuentes

Asumir que RETURNING es portable

SQLite lo documenta explícitamente como una extensión no estándar. Si tu aplicación debe funcionar en varios motores, verifica la sintaxis y el comportamiento del motor objetivo.

Confundir filas devueltas con filas confirmadas definitivamente

Una sentencia puede ejecutarse dentro de una transacción que más tarde termine en ROLLBACK. RETURNING te muestra el resultado de la sentencia; no convierte por sí solo el cambio en un COMMIT.

Esperar que SQLite devuelva cambios indirectos

En SQLite, RETURNING informa las filas modificadas directamente por la sentencia de nivel superior; los cambios adicionales provocados por claves foráneas o triggers no aparecen como filas extra de esa salida.

Práctica guiada

Intermedia · INSERT + DEFAULT

Inserta una incidencia y recupera sus valores efectivos

Crea una tabla temporal incidencias con id INTEGER PRIMARY KEY, titulo TEXT NOT NULL y estado TEXT NOT NULL DEFAULT 'abierta'. Inserta la incidencia «Error de stock» sin indicar id ni estado y devuelve esas tres columnas con RETURNING.

Criterio de éxito: la sentencia devuelve 1 | Error de stock | abierta.

Compatibilidad y diferencias entre motores

PostgreSQL documenta RETURNING para INSERT, UPDATE, DELETE y también MERGE. SQLite lo admite en sentencias de nivel superior INSERT, UPDATE y DELETE desde la versión 3.35.0 y aclara que no forma parte del SQL estándar.

Además, no asumas que una salida RETURNING puede reutilizarse dentro de otra consulta de la misma forma en todos los motores: SQLite documenta restricciones que no son iguales a las capacidades de PostgreSQL. Cuando la portabilidad sea importante, trata esta cláusula como una característica del motor.

Qué debes recordar

  • RETURNING devuelve valores de las filas afectadas por una modificación.
  • Es útil para IDs generados, valores por defecto y comprobación inmediata de cambios.
  • En UPDATE obtienes normalmente los valores nuevos; en DELETE, los de la fila eliminada.
  • No equivale a hacer COMMIT y no sustituye a un SELECT general.
  • Es una característica dependiente del motor: verifica compatibilidad antes de usarla como SQL portable.

Conceptos relacionados

Fuentes técnicas consultadas