SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

Postagem rápida sobre o SQLite UPSERT e a nova cláusula RETURNING.

A cláusula RETURNING


Você pode ler os documentos oficiais aqui.

Muitas vezes nos encontramos querendo retornar alguns dados (provavelmente o id) após inserir registros em nosso banco de dados. Desde a versão 3.35.0 (2021-03-12), SQLite suporta o RETURNING cláusula, que permite retornar uma linha de resultado (ou colunas específicas) para cada linha de banco de dados modificada por um DELETE , UPDATE ou INSERT declaração.

INSERT INTO customers (fullName, birthdateTimestamp, address) 
VALUES ('Andrew Mitch', 643911868, '206 Grange Road, Gillingham') 
RETURNING *;

A consulta acima, após a execução, nos retornará todos os valores inseridos no banco de dados, juntamente com o id de cada fila. Dessa forma, podemos evitar fazer outro SELECT consulta ao banco de dados. Bem legal, hein?

A cláusula UPSERT


Você pode ler os documentos oficiais aqui.

Outro pequeno recurso interessante é o UPSERT cláusula. Isso foi adicionado na versão 3.24.0 (2018-06-04) e causa INSERT para se comportar como um UPDATE ou um no-op , no caso de uma UNIQUE CONSTRAINT ou uma PRIMARY KEY CONSTRAINT violação.

Para elaborar, vamos supor que você tenha um action_records tabela que contém todas as ações disparadas por usuários em users tabela, para uma sessão específica . Quando uma nova ação é acionada, você deseja inserir um novo action_record sem erro, ou, se existente AND tiver o mesmo carimbo de data/hora da sessão (isso é tratado pelo ON CONFLICT cláusula), atualize a antiga. Você também pode adicionar opcionalmente um WHERE declaração que resultará em um no-op , caso não seja atendido. A consulta abaixo deve fazer isso:

-- 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 &RETURNING combinados


Uma coisa que eu realmente gostei é o fato de que você pode combinar essas cláusulas simplesmente adicionando RETURNING * no final da consulta. Desta forma, qualquer linha (ou colunas especificadas), inseridas ou atualizadas, serão retornadas.