137

I want to declare a variable in SQLite and use it in insert operation.

Like in MS SQL:

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

For example, I will need to get last_insert_row and use it in insert.

I have found something about binding but I didn't really fully understood it.

Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
Muhammad Nour
  • 2,109
  • 2
  • 17
  • 24

9 Answers9

123

SQLite doesn't support native variable syntax, but you can achieve virtually the same using an in-memory temp table.

I've used the below approach for large projects and works like a charm.

    /* Create in-memory temp table for variables */
    BEGIN;

    PRAGMA temp_store = 2; /* 2 means use in-memory */
    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
  • 8,464
  • 4
  • 38
  • 49
  • 2
    This works but there are a few remarks, I tried this on spatialite , and there it says you cannot change the temp store from within a transaction. Also, I think you are missing a semicolon after BEGIN. Tx for sharing this solution. – Glenn Plas Dec 29 '13 at 14:52
  • How to increment this? I mean how to increment this variable as if it increments with sequential calls. – Vibhu Jain Aug 23 '17 at 11:43
  • 5
    Temporary tables are not guaranteed to be *in-memory*. That is dependent upon the compiler options and also the `PRAGMA temp_store` setting. In fact, according to [online docs](https://www.sqlite.org/tempfiles.html#the_sqlite_temp_store_compile_time_parameter_and_pragma), the **default setting is to store temporarily files to disk** (which includes files for temporary tables and indices). – C Perkins May 24 '19 at 03:44
  • Will a previously created trigger be able to reference this temp table? – Matheus Rocha Oct 12 '20 at 18:21
  • @CPerkins The docs you linked to say `PRAGMA temp_store = 2` stores **in memory**. – Herman Schoenfeld Apr 26 '21 at 09:53
  • @HermanSchoenfeld Apparently I missed that line when I made the comment, but what I shared is still useful since it shared relevant documentation, and your original code has insufficient comments. I suggest adding an explicit comment exactly at the line of code (not just above the code block). Resolve the magic number by adding something like `/* 2 means use in-memory */`. – C Perkins Apr 27 '21 at 14:21
  • better to always use **IF EXISTS / NOT** when creating or dropping to avoid errors: ( `DROP TABLE IF EXISTS _Variables` ) and (`CREATE TEMP TABLE IF NOT EXISTS _Variables(....` ) – The Doctor Jun 28 '22 at 15:46
107

For a read-only variable (that is, a constant value set once and used anywhere in the query), use a Common Table Expression (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

SQLite WITH clause

DenverCR
  • 1,301
  • 1
  • 7
  • 6
53

Herman's solution works, but it can be simplified because Sqlite allows to store any value type on any field.

Here is a simpler version that uses one Value field declared as TEXT to store any value:

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
  • 8,290
  • 14
  • 64
  • 104
  • 8
    but you should not forget to cast the value to the right type if you want to use it in comparisons or you may get surprising results – vlad_tepesch Sep 21 '18 at 07:39
  • SQLite has an `ANY` type which you should prefer to mis-using a `TEXT` column. It's both clearer from a documentation / schma point of view, and it will work correctly with the recent `STRICT` tables. – Masklinn Feb 23 '23 at 13:53
10

Herman's solution worked for me, but the ... had me mixed up for a bit. I'm including the demo I worked up based on his answer. The additional features in my answer include foreign key support, auto incrementing keys, and use of the last_insert_rowid() function to get the last auto generated key in a transaction.

My need for this information came up when I hit a transaction that required three foreign keys but I could only get the last one with 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
  • 14,352
  • 10
  • 69
  • 100
8

To use the one from denverCR in your example:

WITH tblCTE AS (SELECT "Joe" AS namevar)
SELECT * FROM table, tblCTE
WHERE name = namevar

As a beginner I found other answers too difficult to understand, hope this works

Stefano Verugi
  • 101
  • 1
  • 5
3

After reading all the answers I prefer something like this:

select *
from table, (select 'name' as name) const
where table.name = const.name
Julio
  • 31
  • 1
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31983217) – Shmiel Jun 12 '22 at 19:04
2

Creating "VARIABLE" for use in SQLite SELECT (and some other) statements

CREATE TEMP TABLE IF NOT EXISTS variable AS SELECT '2002' AS _year; --creating the "variable" named "_year" with value "2002"
UPDATE variable SET _year = '2021'; --changing the variable named "_year" assigning "new" value "2021"
SELECT _year FROM variable; --viewing the variable
SELECT 'TEST', (SELECT _year FROM variable) AS _year; --using the variable
SELECT taxyr FROM owndat WHERE taxyr = (SELECT _year FROM variable); --another example of using the variable
SELECT DISTINCT taxyr FROM owndat WHERE taxyr IN ('2022',(SELECT _year FROM variable)); --another example of using the variable
DROP TABLE IF EXISTS variable; --releasing the "variable" if needed to be released
Pepik
  • 111
  • 1
  • 6
-2

I found one solution for assign variables to COLUMN or TABLE:

conn = sqlite3.connect('database.db')
cursor=conn.cursor()
z="Cash_payers"   # bring results from Table 1 , Column: Customers and COLUMN 
# which are pays cash
sorgu_y= Customers #Column name
query1="SELECT  * FROM  Table_1 WHERE " +sorgu_y+ " LIKE ? "
print (query1)
query=(query1)
cursor.execute(query,(z,))

Don't forget input one space between the WHERE and double quotes and between the double quotes and LIKE

Alphard
  • 25
  • 3
-2

Try using Binding Values. You cannot use variables as you do in T-SQL but you can use "parameters". I hope the following link is usefull.Binding Values

Unfamiliar
  • 21
  • 3
  • 30
    you can make your answer richer providing examples. Links can be moved but your examples will be here for future reference. – Pabluez Dec 19 '11 at 15:11