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.


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;

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

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


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;

-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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.