SQLite
 sql >> Datenbank >  >> RDS >> SQLite

Kurzer Beitrag über den SQLite-UPSERT und die neue RETURNING-Klausel.

Die RETURNING-Klausel

Sie können die offiziellen Dokumente hier lesen.

Oft möchten wir einige Daten (wahrscheinlich die ID) zurückgeben, nachdem wir Datensätze in unsere Datenbank eingefügt haben. Ab Version 3.35.0 (2021-03-12) unterstützt SQLite den RETURNING -Klausel, mit der Sie eine Ergebniszeile (oder bestimmte Spalten) für jede geänderte Datenbankzeile durch ein DELETE zurückgeben können , UPDATE oder INSERT Erklärung.

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

Die obige Abfrage gibt uns nach der Ausführung jeden in die Datenbank eingefügten Wert zusammen mit der id zurück jeder Reihe. Auf diese Weise können wir ein weiteres SELECT vermeiden Abfrage an die Datenbank. Ziemlich ordentlich, nicht wahr?

Die UPSERT-Klausel

Sie können die offiziellen Dokumente hier lesen.

Ein weiteres nettes kleines Feature ist der UPSERT Klausel. Dies wurde in Version 3.24.0 hinzugefügt (2018-06-04) und es verursacht INSERT entweder wie ein UPDATE verhalten oder ein no-op , im Falle einer UNIQUE CONSTRAINT oder eine PRIMARY KEY CONSTRAINT Verstoß.

Nehmen wir zur Erläuterung an, Sie haben einen action_records Tabelle, die alle Aktionen enthält, die von Benutzern in users ausgelöst wurden Tabelle, für eine bestimmte Sitzung . Wenn eine neue Aktion ausgelöst wird, möchten Sie entweder einen neuen action_record einfügen ohne Fehler oder, falls vorhanden, AND hat denselben Sitzungszeitstempel (Dies wird vom ON CONFLICT gehandhabt Klausel), aktualisieren Sie die alte. Sie können optional auch ein WHERE hinzufügen -Anweisung, die zu einem no-op führt , falls nicht erfüllt. Die folgende Abfrage sollte es tun:

-- 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 kombiniert

Eine Sache, die mir sehr gut gefallen hat, ist die Tatsache, dass Sie diese Klauseln kombinieren können, indem Sie einfach RETURNING * hinzufügen am Ende der Abfrage. Auf diese Weise wird jede Zeile (oder angegebene Spalte), entweder eingefügt oder aktualisiert, zurückgegeben.