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.
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.
| Sentencia | Uso habitual | Valor que interesa |
|---|---|---|
INSERT | Crear una fila | ID, DEFAULT u otros valores calculados |
UPDATE | Modificar filas | Valores resultantes después del cambio |
DELETE | Eliminar filas | Datos 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.
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;| id | cliente | estado |
|---|---|---|
| 1 | Ana | pendiente |
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.
UPDATE pedidos_returning
SET estado = 'enviado'
WHERE id = 1
RETURNING id, estado;| id | estado |
|---|---|
| 1 | enviado |
DELETE FROM pedidos_returning
WHERE id = 1
RETURNING id, cliente, estado;| id | cliente | estado |
|---|---|---|
| 1 | Ana | enviado |
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.
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
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.
estado con DEFAULT 'abierta'.INSERT solo necesitas la columna titulo.RETURNING id, titulo, estado.Solución razonada
CREATE TEMP TABLE incidencias (
id INTEGER PRIMARY KEY,
titulo TEXT NOT NULL,
estado TEXT NOT NULL DEFAULT 'abierta'
);
INSERT INTO incidencias (titulo)
VALUES ('Error de stock')
RETURNING id, titulo, estado;| id | titulo | estado |
|---|---|---|
| 1 | Error de stock | abierta |
La fila se inserta una sola vez y la propia sentencia devuelve tanto el identificador generado como el valor aplicado por DEFAULT.
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
RETURNINGdevuelve valores de las filas afectadas por una modificación.- Es útil para IDs generados, valores por defecto y comprobación inmediata de cambios.
- En
UPDATEobtienes normalmente los valores nuevos; enDELETE, los de la fila eliminada. - No equivale a hacer
COMMITy no sustituye a unSELECTgeneral. - Es una característica dependiente del motor: verifica compatibilidad antes de usarla como SQL portable.