sql >> Base de Datos >  >> RDS >> SQLite

Publicación rápida sobre SQLite UPSERT y la nueva cláusula RETURNING.

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.