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


92

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

2
2018
MarshallMa

回答:


92

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 2013

1
@WindRider:予約語との衝突を避けるため。私の習慣ですが、この場合は不要なので、削除されます。
Herman Schoenfeld

2
これは機能しますが、いくつかの注意点があります。spatialiteで試してみましたが、トランザクション内から一時ストアを変更することはできません。また、BEGINの後にセミコロンがないと思います。このソリューションを共有するためのTx。
Glenn Plas

これを増やす方法は?この変数を逐次呼び出しでインクリメントするようにインクリメントする方法を意味します。
Vibhu Jain 2017

2
一時テーブルは、メモリ内にあることが保証されていません。これは、コンパイラオプションとPRAGMA temp_store設定にも依存します。実際、オンラインドキュメントによると、デフォルトの設定では、一時ファイルをディスクに保存します(一時テーブルとインデックスのファイルを含みます)。
Cパーキンス

43

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

3
ただし、比較で使用する場合は、値を正しい型にキャストすることを忘れないでください。そうしないと、驚くべき結果が得られる場合があります
vlad_tepesch

26

読み取り専用変数(つまり、定数値が1回設定され、クエリの任意の場所で使用される)の場合は、共通テーブル式(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句


1
これは最もエレガントな答えです
imo

これが私が探していた答えのタイプです。
John Baber-Lucero

9

ハーマンの解決策は私にはうまく...いきましたが、少し混乱しました。私は彼の答えに基づいて作成したデモを含めています。私の回答の追加機能には、外部キーのサポート、自動インクリメントキー、および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;

-1

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


26
あなたはあなたの答えを例を提供してより豊かにすることができます。リンクは移動できますが、あなたの例は今後の参考のためにここにあります。
Pabluez 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.