Declare a variável no SQLite e use-a

92

Quero declarar uma variável no SQLite e usá-la na insertoperação.

Como no MS SQL:

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

Por exemplo, vou precisar obter last_insert_rowe usar em insert.

Eu descobri algo sobre vinculação, mas não entendi bem.

Muhammad Nour
fonte
7
sqlite não suporta isso.
Dan D.
2
espero que haja uma solução melhor agora - agosto de 2018
MarshallMa

Respostas:

92

O SQLite não oferece suporte à sintaxe de variável nativa, mas você pode obter virtualmente o mesmo usando uma tabela temporária na memória.

Usei a abordagem abaixo para grandes projetos e funciona perfeitamente.

    /* 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
fonte
Para que são usados ​​esses [] colchetes?
WindRider
1
@WindRider: para evitar confrontos com palavras reservadas. Um hábito meu, mas desnecessário neste caso, então eles são removidos.
Herman Schoenfeld
2
Isso funciona, mas existem alguns comentários, eu tentei isso em espacialite e lá diz que você não pode alterar o armazenamento temporário de dentro de uma transação. Além disso, acho que falta um ponto-e-vírgula após BEGIN. Tx por compartilhar esta solução.
Glenn Plas
Como incrementar isso? Quero dizer como incrementar esta variável como se fosse incrementada com chamadas sequenciais.
Vibhu Jain
2
Não é garantido que as tabelas temporárias estejam na memória . Isso depende das opções do compilador e também da PRAGMA temp_storeconfiguração. Na verdade, de acordo com os documentos online , a configuração padrão é armazenar arquivos temporariamente no disco (o que inclui arquivos para tabelas e índices temporários).
C Perkins
43

A solução de Herman funciona, mas pode ser simplificada porque o Sqlite permite armazenar qualquer tipo de valor em qualquer campo.

Esta é uma versão mais simples que usa um Valuecampo declarado TEXTpara armazenar qualquer 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
fonte
3
mas você não deve se esquecer de converter o valor para o tipo certo se quiser usá-lo em comparações ou poderá obter resultados surpreendentes
vlad_tepesch
26

Para uma variável somente leitura (ou seja, um valor constante definido uma vez e usado em qualquer lugar na consulta), use uma Expressão de tabela comum (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
fonte
1
Esta é a resposta mais elegante imo
Vladtn
Esse é o tipo de resposta que eu procurava.
John Baber-Lucero
9

A solução de Herman funcionou para mim, mas ...me confundiu um pouco. Estou incluindo a demonstração que desenvolvi com base na resposta dele. Os recursos adicionais em minha resposta incluem suporte para chave estrangeira, chaves de incremento automático e uso da last_insert_rowid()função para obter a última chave gerada automaticamente em uma transação.

Minha necessidade dessa informação surgiu quando achei uma transação que exigia três chaves estrangeiras, mas só consegui obter a última com 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
fonte
-1

Tente usar valores vinculativos. Você não pode usar variáveis ​​como no T-SQL, mas pode usar "parâmetros". Espero que o link a seguir seja útil. Valores Vinculativos

Desconhecido
fonte
26
você pode tornar sua resposta mais rica fornecendo exemplos. Os links podem ser movidos, mas seus exemplos estarão aqui para referência futura.
Pabluez