SQLite
 sql >> Base de données >  >> RDS >> SQLite

Message rapide sur SQLite UPSERT et la nouvelle clause RETURNING.

La clause RETURNING

Vous pouvez lire les documents officiels ici.

Plusieurs fois, nous nous retrouvons à vouloir renvoyer certaines données (probablement l'identifiant) après avoir inséré des enregistrements dans notre base de données. Depuis la version 3.35.0 (2021-03-12), SQLite prend en charge le RETURNING clause, qui vous permet de retourner une ligne de résultat (ou des colonnes spécifiques) pour chaque ligne de base de données modifiée par un DELETE , UPDATE ou INSERT déclaration.

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

La requête ci-dessus, après exécution, nous renverra chaque valeur insérée dans la base de données, ainsi que le id de chaque rangée. De cette façon, nous pouvons éviter de faire un autre SELECT requête à la base de données. Plutôt chouette, hein ?

La clause UPSERT

Vous pouvez lire les documents officiels ici.

Une autre petite fonctionnalité intéressante est le UPSERT clause. Cela a été ajouté dans la version 3.24.0 (2018-06-04) et cela provoque INSERT se comporter soit comme un UPDATE ou un no-op , en cas de UNIQUE CONSTRAINT ou une PRIMARY KEY CONSTRAINT violation.

Pour élaborer, supposons que vous ayez un action_records table qui contient toutes les actions déclenchées par les utilisateurs dans le users tableau, pour une session spécifique . Lorsqu'une nouvelle action est déclenchée, vous souhaitez soit insérer un nouveau action_record sans erreur, ou, si ET existant a le même horodatage de session (cela est géré par le ON CONFLICT clause), mettre à jour l'ancienne. Vous pouvez également éventuellement ajouter un WHERE déclaration qui se traduira par un no-op , s'il n'est pas atteint. La requête ci-dessous devrait le faire :

-- 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 &RETOUR combinés

Une chose que j'ai vraiment aimée est le fait que vous pouvez combiner ces clauses en ajoutant simplement RETURNING * à la fin de la requête. De cette façon, toute ligne (ou colonne spécifiée), insérée ou mise à jour, sera renvoyée.