La cláusula RETURNING
Puede leer los documentos oficiales aquí.
Muchas veces nos encontramos queriendo devolver algún dato (probablemente el id) después de insertar registros en nuestra base de datos. Desde la versión 3.35.0
(2021-03-12), SQLite admite RETURNING
cláusula, que le permite devolver una fila de resultados (o columnas específicas) para cada fila de base de datos modificada mediante DELETE
, UPDATE
o INSERT
declaración.
INSERT INTO customers (fullName, birthdateTimestamp, address)
VALUES ('Andrew Mitch', 643911868, '206 Grange Road, Gillingham')
RETURNING *;
La consulta anterior, después de la ejecución, nos devolverá todos los valores insertados en la base de datos, junto con el id
de cada fila. De esta manera podemos evitar hacer otro SELECT
consulta a la base de datos. Bastante ordenado, ¿eh?
La cláusula UPSERT
Puede leer los documentos oficiales aquí.
Otra característica pequeña y agradable es el UPSERT
cláusula. Esto se agregó en la versión 3.24.0
(2018-06-04) y causa INSERT
comportarse como un UPDATE
o un no-op
, en caso de una UNIQUE CONSTRAINT
o una PRIMARY KEY CONSTRAINT
violación.
Para elaborar, supongamos que tiene un action_records
tabla que contiene todas las acciones realizadas por los usuarios en el users
tabla, para una sesión específica . Cuando se activa una nueva acción, desea insertar un nuevo action_record
sin error, o, si existe Y tiene la misma marca de tiempo de sesión (esto es manejado por ON CONFLICT
cláusula), actualice la anterior. Opcionalmente, también puede agregar un WHERE
declaración que resultará en un no-op
, si no se cumple. La siguiente consulta debería hacerlo:
-- Create users table and assign userID and sessionStartTimestamp as a UNIQUE CONSTRAINT.
DROP TABLE IF EXISTS "action_records";
CREATE TABLE IF NOT EXISTS "action_records" (
"id" INTEGER NOT NULL,
"userID" INTEGER NOT NULL,
"sessionStartTimestamp" INTEGER NOT NULL,
"errorMsg" TEXT,
PRIMARY KEY("id" AUTOINCREMENT),
FOREIGN KEY("userID") REFERENCES "users"("id") ON DELETE CASCADE,
UNIQUE(userID, sessionStartTimestamp)
);
-- Insert new record or update the old one based on UNIQUE_CONSTRAINT OF userID & session_start_timestamp
INSERT INTO action_records (userID, errorMsg, sessionStartTimestamp)
VALUES (258, null, 643911868)
ON CONFLICT(userID, sessionStartTimestamp) -- Conflict when a record for the same user and session exists
DO UPDATE SET errorMsg = 'An error occured'
WHERE errorMsg IS NOT NULL -- This will be a no-op in case there is already an error and you don't want to update it
RETURNING *; -- Optionally adding RETURNING to retrieve any number of columns we want
UPSERT Y RETORNO combinados
Una cosa que realmente me gustó es el hecho de que puedes combinar esas cláusulas simplemente agregando RETURNING *
al final de la consulta. De esta forma, se devolverá cualquier fila (o columna especificada), ya sea insertada o actualizada.