Déclarez une variable dans SQLite et utilisez-la

92

Je veux déclarer une variable dans SQLite et l'utiliser en insertfonctionnement.

Comme dans MS SQL:

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

Par exemple, je devrai l'obtenir last_insert_rowet l'utiliser insert.

J'ai trouvé quelque chose sur la reliure mais je ne l'ai pas vraiment bien compris.

Muhammad Nour
la source
7
sqlite ne prend pas en charge cela.
Dan D.
2
j'espère qu'il y a une meilleure solution maintenant - août 2018
MarshallMa

Réponses:

92

SQLite ne prend pas en charge la syntaxe de variable native, mais vous pouvez obtenir pratiquement la même chose en utilisant une table temporaire en mémoire.

J'ai utilisé l'approche ci-dessous pour les grands projets et fonctionne comme un charme.

    /* 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;
Herman Schoenfeld
la source
À quoi servent ces crochets []?
WindRider
1
@WindRider: pour éviter tout conflit avec des mots réservés. Une de mes habitudes mais inutile dans ce cas, donc ils sont supprimés.
Herman Schoenfeld
2
Cela fonctionne mais il y a quelques remarques, j'ai essayé cela sur spatialite, et là, il est dit que vous ne pouvez pas changer le magasin temporaire à partir d'une transaction. De plus, je pense qu'il vous manque un point-virgule après BEGIN. Tx pour partager cette solution.
Glenn Plas
Comment incrémenter cela? Je veux dire comment incrémenter cette variable comme si elle incrémentait avec des appels séquentiels.
Vibhu Jain
2
Les tables temporaires ne sont pas garanties d'être en mémoire . Cela dépend des options du compilateur et également du PRAGMA temp_storeparamètre. En fait, selon la documentation en ligne , le paramètre par défaut est de stocker temporairement les fichiers sur le disque (qui comprend les fichiers pour les tables temporaires et les index).
C Perkins
43

La solution d'Herman fonctionne, mais elle peut être simplifiée car Sqlite permet de stocker n'importe quel type de valeur sur n'importe quel champ.

Voici une version plus simple qui utilise un Valuechamp déclaré comme TEXTpour stocker n'importe quelle valeur:

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';
pochoir
la source
3
mais vous ne devez pas oublier de convertir la valeur dans le bon type si vous souhaitez l'utiliser dans des comparaisons ou vous pouvez obtenir des résultats surprenants
vlad_tepesch
27

Pour une variable en lecture seule (c'est-à-dire une valeur constante définie une fois et utilisée n'importe où dans la requête), utilisez une expression de table commune (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

Clause SQLite WITH

DenverCR
la source
1
C'est la réponse la plus élégante imo
Vladtn
C'est le type de réponse que je recherchais.
John Baber-Lucero
9

La solution d'Herman a fonctionné pour moi, mais cela ...m'a un peu mélangé. J'inclus la démo que j'ai élaborée en fonction de sa réponse. Les fonctionnalités supplémentaires de ma réponse incluent la prise en charge des clés étrangères, les clés à incrémentation automatique et l'utilisation de la last_insert_rowid()fonction pour obtenir la dernière clé générée automatiquement dans une transaction.

Mon besoin de ces informations est apparu lorsque j'ai frappé une transaction qui nécessitait trois clés étrangères, mais je ne pouvais obtenir que la dernière avec 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;
ThisClark
la source
-1

Essayez d'utiliser des valeurs de liaison. Vous ne pouvez pas utiliser de variables comme vous le faites dans T-SQL mais vous pouvez utiliser des "paramètres". J'espère que le lien suivant est utile. Valeurs de liaison

Inconnu
la source
26
vous pouvez enrichir votre réponse en fournissant des exemples. Les liens peuvent être déplacés mais vos exemples seront ici pour référence future.
Pabluez