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.