Khai báo biến trong SQLite và sử dụng nó


91

Tôi muốn khai báo một biến trong SQLite và sử dụng nó trong inserthoạt động.

Giống như trong MS SQL:

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

Ví dụ, tôi sẽ cần lấy last_insert_rowvà sử dụng nó trong insert.

Tôi đã tìm thấy một cái gì đó về ràng buộc nhưng tôi không thực sự hiểu đầy đủ về nó.


7
sqlite không hỗ trợ điều này.
Dan D.

2
hy vọng có một giải pháp tốt hơn bây giờ - tháng 8 năm 2018
MarshallMa

Câu trả lời:


93

SQLite không hỗ trợ cú pháp biến gốc, nhưng bạn có thể đạt được gần như tương tự bằng cách sử dụng bảng tạm thời trong bộ nhớ.

Tôi đã sử dụng cách tiếp cận dưới đây cho các dự án lớn và hoạt động như một sự quyến rũ.

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

Những dấu ngoặc [] này được sử dụng để làm gì?
WindRider

1
@WindRider: để tránh mọi xung đột với các từ dành riêng. Một thói quen của tôi nhưng không cần thiết trong trường hợp này, vì vậy chúng bị loại bỏ.
Herman Schoenfeld

2
Điều này hoạt động nhưng có một số nhận xét, tôi đã thử điều này trên spatialite và ở đó nó nói rằng bạn không thể thay đổi cửa hàng tạm thời từ trong một giao dịch. Ngoài ra, tôi nghĩ bạn đang thiếu dấu chấm phẩy sau BEGIN. Tx để chia sẻ giải pháp này.
Glenn Plas

Làm thế nào để tăng điều này? Ý tôi là cách tăng biến này như thể nó tăng với các lệnh gọi tuần tự.
Vibhu Jain,

1
Các bảng tạm thời không được đảm bảo là trong bộ nhớ . Điều đó phụ thuộc vào các tùy chọn trình biên dịch và PRAGMA temp_storecài đặt. Trên thực tế, theo các tài liệu trực tuyến , cài đặt mặc định là lưu trữ các tệp tạm thời vào đĩa (bao gồm các tệp cho các bảng và chỉ mục tạm thời).
C Perkins

44

Giải pháp của Herman hoạt động, nhưng nó có thể được đơn giản hóa vì Sqlite cho phép lưu trữ bất kỳ kiểu giá trị nào trên bất kỳ trường nào.

Đây là một phiên bản đơn giản hơn sử dụng một Valuetrường được khai báo là TEXTđể lưu trữ bất kỳ giá trị nào:

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

2
nhưng bạn không nên quên bỏ các giá trị cho đúng loại nếu bạn muốn sử dụng nó trong sự so sánh hoặc bạn có thể có được kết quả đáng ngạc nhiên
vlad_tepesch

22

Đối với biến chỉ đọc (nghĩa là một giá trị không đổi được đặt một lần và được sử dụng ở bất kỳ đâu trong truy vấn), hãy sử dụng Biểu thức bảng chung (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

Mệnh đề VỚI SQLite


Đây là câu trả lời thanh lịch nhất imo
Vladtn

Đây là loại câu trả lời mà tôi đang tìm kiếm.
John Baber-Lucero

9

Giải pháp của Herman có hiệu quả với tôi, nhưng giải pháp của tôi ...đã khiến tôi bị xáo trộn một chút. Tôi bao gồm bản demo mà tôi đã làm việc dựa trên câu trả lời của anh ấy. Các tính năng bổ sung trong câu trả lời của tôi bao gồm hỗ trợ khóa ngoại, khóa tăng tự động và sử dụng last_insert_rowid()chức năng lấy khóa được tạo tự động cuối cùng trong giao dịch.

Nhu cầu của tôi về thông tin này xuất hiện khi tôi thực hiện một giao dịch yêu cầu ba khóa ngoại nhưng tôi chỉ có thể nhận được khóa cuối cùng 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

Hãy thử sử dụng Giá trị ràng buộc. Bạn không thể sử dụng các biến như bạn làm trong T-SQL nhưng bạn có thể sử dụng "tham số". Tôi hy vọng liên kết sau là hữu ích. Giá trị ràng buộc


26
bạn có thể làm cho câu trả lời của mình phong phú hơn bằng cách cung cấp các ví dụ. Các liên kết có thể được di chuyển nhưng các ví dụ của bạn sẽ ở đây để tham khảo trong tương lai.
Pabluez 19/12/11
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.