Dichiara la variabile in SQLite e usala


92

Voglio dichiarare una variabile in SQLite e usarla durante il insertfunzionamento.

Come in MS SQL:

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

Ad esempio, dovrò scaricarlo last_insert_rowe usarlo in insert.

Ho trovato qualcosa sull'associazione ma non l'ho capito appieno.


7
sqlite non lo supporta.
Dan D.

2
spero che ci sia una soluzione migliore ora - agosto 2018
MarshallMa

Risposte:


92

SQLite non supporta la sintassi delle variabili native, ma puoi ottenere praticamente lo stesso utilizzando una tabella temporanea in memoria.

Ho usato l'approccio seguente per progetti di grandi dimensioni e funziona come un fascino.

    /* 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;

A cosa servono queste parentesi []?
WindRider

1
@WindRider: per evitare scontri con parole riservate. Una mia abitudine ma non necessaria in questo caso, quindi vengono rimosse.
Herman Schoenfeld

2
Funziona ma ci sono alcune osservazioni, l'ho provato su spatialite, e lì dice che non è possibile modificare l'archivio temporaneo dall'interno di una transazione. Inoltre, penso che manchi un punto e virgola dopo BEGIN. Tx per aver condiviso questa soluzione.
Glenn Plas

Come incrementarlo? Intendo come incrementare questa variabile come se aumentasse con chiamate sequenziali.
Vibhu Jain

2
Non è garantito che le tabelle temporanee siano in memoria . Ciò dipende dalle opzioni del compilatore e anche PRAGMA temp_storedall'impostazione. In effetti, secondo la documentazione in linea , l' impostazione predefinita è di archiviare temporaneamente i file su disco (che include file per tabelle e indici temporanei).
C Perkins

43

La soluzione di Herman funziona, ma può essere semplificata perché Sqlite consente di memorizzare qualsiasi tipo di valore su qualsiasi campo.

Ecco una versione più semplice che utilizza un Valuecampo dichiarato come TEXTper memorizzare qualsiasi valore:

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';

3
ma non dovresti dimenticare di lanciare il valore sul tipo giusto se vuoi usarlo nei confronti o potresti ottenere risultati sorprendenti
vlad_tepesch

26

Per una variabile di sola lettura (ovvero un valore costante impostato una volta e utilizzato in qualsiasi punto della query), utilizzare un'espressione di tabella comune (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

Clausola WITH SQLite


1
Questa è la risposta più elegante imo
Vladtn

Questo è il tipo di risposta che stavo cercando.
John Baber-Lucero

9

La soluzione di Herman ha funzionato per me, ma ...mi ha confuso per un po '. Includo la demo che ho elaborato in base alla sua risposta. Le funzionalità aggiuntive nella mia risposta includono il supporto della chiave esterna, le chiavi con incremento automatico e l'uso della last_insert_rowid()funzione per ottenere l'ultima chiave generata automaticamente in una transazione.

Il mio bisogno di queste informazioni è emerso quando ho effettuato una transazione che richiedeva tre chiavi esterne, ma ho potuto ottenere solo l'ultima con 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

Prova a utilizzare i valori vincolanti. Non puoi usare le variabili come fai in T-SQL ma puoi usare i "parametri". Spero che il seguente collegamento sia utile. Valori vincolanti


26
puoi arricchire la tua risposta fornendo esempi. I collegamenti possono essere spostati ma i tuoi esempi saranno qui per riferimento futuro.
Pabluez
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.