Оголосіть змінну в SQLite і використовуйте її


94

Я хочу оголосити змінну в SQLite і використовувати її в insert роботі.

Як у MS SQL:

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

Наприклад, мені потрібно буде отримати last_insert_rowта використовувати його в insert.

Я знайшов щось про прив'язку, але насправді цього не повністю зрозумів.


7
sqlite цього не підтримує.
Dan D.

2
сподіваюся, зараз є краще рішення - серпень 2018 р.
MarshallMa

Відповіді:


93

SQLite не підтримує власний синтаксис змінних, але ви можете досягти практично того ж, використовуючи тимчасову таблицю в пам'яті.

Я використовував наведений нижче підхід для великих проектів і працює як шарм.

    /* 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;

Для чого використовуються ці [] дужки?
WindRider

1
@WindRider: щоб уникнути будь-яких сутичок із зарезервованими словами. Моя звичка, але в цьому випадку непотрібна, тому їх усувають.
Herman Schoenfeld

2
Це працює, але є кілька зауважень, я спробував це на spatialite, і там сказано, що ви не можете змінити тимчасовий магазин всередині транзакції. Крім того, я думаю, вам не вистачає крапки з комою після BEGIN. Tx для обміну цим рішенням.
Glenn Plas

Як це збільшити? Я маю на увазі, як збільшити цю змінну так, ніби вона збільшується за допомогою послідовних викликів.
Vibhu Jain

2
Тимчасові таблиці не гарантуються в пам'яті . Це залежить від параметрів компілятора, а також PRAGMA temp_storeналаштувань. Насправді, згідно з онлайн-документами , налаштування за замовчуванням - тимчасове зберігання файлів на диску (що включає файли для тимчасових таблиць та індексів).
С Перкінс,

43

Рішення Германа працює, але його можна спростити, оскільки Sqlite дозволяє зберігати будь-який тип значення в будь-якому полі.

Ось простіша версія, яка використовує одне Valueполе, оголошене як TEXTдля зберігання будь-якого значення:

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
але вам не слід забувати відкинути значення до потрібного типу, якщо ви хочете використовувати його для порівняння або ж можете отримати дивовижні результати
vlad_tepesch

33

Для змінної, доступної лише для читання (тобто константи, встановленої один раз і використовуваної в будь-якому місці запиту), використовуйте загальний вираз таблиці (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


2
Це найелегантніша відповідь imo
Vladtn

1
Це той тип відповіді, який я шукав.
Джон Бабер-Люсеро,

9

Рішення Германа спрацювало для мене, але ...мене трохи змішало. Я включаю демо, яке я розробив на основі його відповіді. Додаткові функції моєї відповіді включають підтримку зовнішнього ключа, автоматичне збільшення клавіш та використання last_insert_rowid()функції для отримання останнього автоматично згенерованого ключа в транзакції.

Моя потреба в цій інформації з’явилася, коли я здійснив транзакцію, яка вимагала трьох зовнішніх ключів, але я міг отримати лише останній 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;

дякую за гарний приклад, справді набагато корисніший, ніж думки та посилання
splaisan

-1

Спробуйте використовувати значення прив'язки. Ви не можете використовувати змінні, як у T-SQL, але можете використовувати "параметри". Я сподіваюся, що наступне посилання є корисним. Зв'язуючі значення


26
Ви можете зробити свою відповідь багатшою, надаючи приклади. Посилання можна переміщати, але ваші приклади будуть тут для подальшого використання.
Pabluez
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.