web-dev-qa-db-ja.com

SQLiteで変数を宣言して使用する

SQLiteで変数を宣言し、insert操作で使用したい。

MS SQLのように:

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

たとえば、last_insert_rowを取得し、insertで使用する必要があります。

バインディングについて何かを見つけましたが、それを完全には理解していませんでした。

81
Muhammad Nour

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

Hermanのソリューションは機能しますが、Sqliteでは任意のフィールドに任意の値タイプを保存できるため、単純化できます。

Valueとして宣言された1つの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';
41
stenci

ハーマンのソリューションは私にとってはうまくいきましたが、...は少し混乱してしまいました。私は彼の答えに基づいて作成したデモを含めています。私の答えの追加機能には、外部キーのサポート、キーの自動インクリメント、およびトランザクションで最後に自動生成されたキーを取得するためのlast_insert_rowid()関数の使用が含まれます。

この情報が必要なのは、3つの外部キーを必要とするトランザクションを見つけたときでしたが、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;
9
ThisClark

読み取り専用変数(クエリ全体で同じ値を使用)の場合は、共通テーブル式(CTE)を使用します。

WITH var AS (SELECT 'name' AS name, 10 AS more)
SELECT *, (table.cost + var.more) AS result 
FROM table, var 
WHERE table.name = var.name

SQLite WITH句

1
DenverCR

バインディング値を使用してみてください。 T-SQLのように変数を使用することはできませんが、「パラメーター」は使用できます。次のリンクが役立つことを願っています。 値のバインド

1
Unfamiliar