Declarar variable en SQLite y usarla

94

Quiero declarar una variable en SQLite y usarla en insertfuncionamiento.

Como en MS SQL:

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

Por ejemplo, necesitaré obtenerlo last_insert_rowy usarlo insert.

Encontré algo sobre la vinculación, pero realmente no lo entendí completamente.

Muhammad Nour
fuente
7
sqlite no admite esto.
Dan D.
2
Espero que haya una mejor solución ahora - Agosto 2018
MarshallMa

Respuestas:

93

SQLite no admite la sintaxis de variables nativas, pero puede lograr prácticamente lo mismo utilizando una tabla temporal en memoria.

He utilizado el siguiente enfoque para proyectos grandes y funciona como un encanto.

    /* 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
fuente
¿Para qué se utilizan estos [] corchetes?
WindRider
1
@WindRider: para evitar conflictos con palabras reservadas. Un hábito mío pero innecesario en este caso, por lo que se eliminan.
Herman Schoenfeld
2
Esto funciona, pero hay algunos comentarios, probé esto en Spatialite y allí dice que no puede cambiar la tienda temporal desde una transacción. Además, creo que le falta un punto y coma después de BEGIN. Tx por compartir esta solución.
Glenn Plas
¿Cómo incrementar esto? Me refiero a cómo incrementar esta variable como si se incrementara con llamadas secuenciales.
Vibhu Jain
2
No se garantiza que las tablas temporales estén en memoria . Eso depende de las opciones del compilador y también de la PRAGMA temp_storeconfiguración. De hecho, de acuerdo con los documentos en línea , la configuración predeterminada es almacenar archivos temporalmente en el disco (que incluye archivos para tablas e índices temporales).
C Perkins
43

La solución de Herman funciona, pero se puede simplificar porque Sqlite permite almacenar cualquier tipo de valor en cualquier campo.

Aquí hay una versión más simple que usa un Valuecampo declarado como TEXTpara almacenar cualquier valor:

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';
stenci
fuente
3
pero no debe olvidar lanzar el valor al tipo correcto si desea usarlo en comparaciones o puede obtener resultados sorprendentes
vlad_tepesch
33

Para una variable de solo lectura (es decir, un valor constante establecido una vez y utilizado en cualquier lugar de la consulta), use una expresión de tabla común (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

Cláusula SQLite WITH

DenverCR
fuente
2
Esta es la respuesta más elegante imo
Vladtn
1
Este es el tipo de respuesta que estaba buscando.
John Baber-Lucero
9

La solución de Herman funcionó para mí, pero ...me confundió un poco. Incluyo la demostración que preparé según su respuesta. Las características adicionales en mi respuesta incluyen soporte de clave externa, claves de incremento automático y el uso de la last_insert_rowid()función para obtener la última clave generada automáticamente en una transacción.

Mi necesidad de esta información surgió cuando llegué a una transacción que requería tres claves externas pero solo pude obtener la última 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;
ThisClark
fuente
gracias por el buen ejemplo, de hecho mucho más útil que las opiniones y los enlaces
splaisan
-1

Intente usar Binding Values. No puede usar variables como lo hace en T-SQL, pero puede usar "parámetros". Espero que el siguiente enlace sea de utilidad. Valores vinculantes

Desconocido
fuente
26
puede enriquecer su respuesta proporcionando ejemplos. Los enlaces se pueden mover, pero sus ejemplos estarán aquí para referencia futura.
Pabluez