Deklarieren Sie die Variable in SQLite und verwenden Sie sie


91

Ich möchte eine Variable in SQLite deklarieren und im insertBetrieb verwenden.

Wie in MS SQL:

declare @name as varchar(10)
set name = 'name'
select * from table where name = @name

Zum Beispiel muss ich es bekommen last_insert_rowund verwenden in insert.

Ich habe etwas über das Binden gefunden, aber ich habe es nicht wirklich verstanden.


7
SQLite unterstützt dies nicht.
Dan D.

2
Ich hoffe, es gibt jetzt eine bessere Lösung - August 2018
MarshallMa

Antworten:


93

SQLite unterstützt keine native Variablensyntax, aber Sie können praktisch dasselbe mit einer temporären Tabelle im Speicher erreichen.

Ich habe den folgenden Ansatz für große Projekte verwendet und funktioniert wie ein Zauber.

    /* Create in-memory temp table for variables */
    BEGIN;

    PRAGMA temp_store = 2;
    CREATE TEMP TABLE _Variables(Name TEXT PRIMARY KEY, RealValue REAL, IntegerValue INTEGER, BlobValue BLOB, TextValue TEXT);

    /* Declaring a variable */
    INSERT INTO _Variables (Name) VALUES ('VariableName');

    /* Assigning a variable (pick the right storage class) */
    UPDATE _Variables SET IntegerValue = ... WHERE Name = 'VariableName';

    /* Getting variable value (use within expression) */
    ... (SELECT coalesce(RealValue, IntegerValue, BlobValue, TextValue) FROM _Variables WHERE Name = 'VariableName' LIMIT 1) ...

    DROP TABLE _Variables;
    END;

Wofür werden diese [] Klammern verwendet?
WindRider

1
@WindRider: um Konflikte mit reservierten Wörtern zu vermeiden. Eine Gewohnheit von mir, aber in diesem Fall unnötig, also werden sie entfernt.
Herman Schönfeld

2
Dies funktioniert, aber es gibt einige Anmerkungen. Ich habe dies bei Spatialite versucht. Dort heißt es, dass Sie den temporären Speicher nicht innerhalb einer Transaktion ändern können. Ich denke auch, dass Ihnen nach BEGIN ein Semikolon fehlt. Tx für die Freigabe dieser Lösung.
Glenn Plas

Wie kann man das erhöhen? Ich meine, wie man diese Variable erhöht, als ob sie mit sequentiellen Aufrufen erhöht wird.
Vibhu Jain

1
Es wird nicht garantiert, dass temporäre Tabellen im Speicher sind . Das hängt von den Compileroptionen und auch von der PRAGMA temp_storeEinstellung ab. Laut Online-Dokumenten besteht die Standardeinstellung darin, temporäre Dateien auf der Festplatte zu speichern (einschließlich Dateien für temporäre Tabellen und Indizes).
C Perkins

44

Hermans Lösung funktioniert, kann aber vereinfacht werden, da mit Sqlite jeder Werttyp in jedem Feld gespeichert werden kann.

Hier ist eine einfachere Version, die ein ValueFeld verwendet, das TEXTzum Speichern eines beliebigen Werts deklariert ist:

CREATE TEMP TABLE IF NOT EXISTS Variables (Name TEXT PRIMARY KEY, Value TEXT);

INSERT OR REPLACE INTO Variables VALUES ('VarStr', 'Val1');
INSERT OR REPLACE INTO Variables VALUES ('VarInt', 123);
INSERT OR REPLACE INTO Variables VALUES ('VarBlob', x'12345678');

SELECT Value
  FROM Variables
 WHERE Name = 'VarStr'
UNION ALL
SELECT Value
  FROM Variables
 WHERE Name = 'VarInt'
UNION ALL
SELECT Value
  FROM Variables
 WHERE Name = 'VarBlob';

2
Sie sollten jedoch nicht vergessen, den Wert in den richtigen Typ
umzuwandeln,

22

Verwenden Sie für eine schreibgeschützte Variable (dh einen einmal festgelegten Konstantenwert, der an einer beliebigen Stelle in der Abfrage verwendet wird) einen Common Table Expression (CTE).

WITH const AS (SELECT 'name' AS name, 10 AS more)
SELECT table.cost, (table.cost + const.more) AS newCost
FROM table, const 
WHERE table.name = const.name

SQLite WITH-Klausel


Dies ist die eleganteste Antwort imo
Vladtn

Dies ist die Art von Antwort, nach der ich gesucht habe.
John Baber-Lucero

9

Hermans Lösung hat bei mir funktioniert, aber das ...hat mich ein bisschen durcheinander gebracht. Ich füge die Demo hinzu, die ich basierend auf seiner Antwort ausgearbeitet habe. Zu den zusätzlichen Funktionen in meiner Antwort gehören die Unterstützung von Fremdschlüsseln, das automatische Inkrementieren von Schlüsseln und die Verwendung der last_insert_rowid()Funktion zum Abrufen des letzten automatisch generierten Schlüssels in einer Transaktion.

Mein Bedarf an diesen Informationen kam auf, als ich eine Transaktion traf, für die drei Fremdschlüssel erforderlich waren, aber ich konnte nur den letzten mit erhalten last_insert_rowid().

PRAGMA foreign_keys = ON;   -- sqlite foreign key support is off by default
PRAGMA temp_store = 2;      -- store temp table in memory, not on disk

CREATE TABLE Foo(
    Thing1 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
);

CREATE TABLE Bar(
    Thing2 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    FOREIGN KEY(Thing2) REFERENCES Foo(Thing1)
);

BEGIN TRANSACTION;

CREATE TEMP TABLE _Variables(Key TEXT, Value INTEGER);

INSERT INTO Foo(Thing1)
VALUES(2);

INSERT INTO _Variables(Key, Value)
VALUES('FooThing', last_insert_rowid());

INSERT INTO Bar(Thing2)
VALUES((SELECT Value FROM _Variables WHERE Key = 'FooThing'));

DROP TABLE _Variables;

END TRANSACTION;

-1

Versuchen Sie es mit Bindungswerten. Sie können keine Variablen wie in T-SQL verwenden, aber Sie können "Parameter" verwenden. Ich hoffe der folgende Link ist nützlich. Bindungswerte


26
Sie können Ihre Antwort anhand von Beispielen bereichern. Links können verschoben werden, aber Ihre Beispiele dienen hier als zukünftige Referenz.
Pabluez
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.