2011-07-13 22 views
11

Tôi muốn sử dụng SQLite FTS3 (FTS4, trên thực tế) để chỉ một bảng với các cột số nguyên, khái niệm một cái gì đó như thế này:Sử dụng SQLite FTS3 với các cột INTEGER

CREATE VIRTUAL TABLE whole (document INTEGER, page INTEGER, content TEXT, 
    UNIQUE(document, page)) USING fts4(); 

Tôi biết rằng FTS3 đối xử với tất cả các cột khác hơn rowid như TEXT, vì vậy tôi sẽ phải sử dụng hai bảng:

CREATE VIRTUAL TABLE data USING fts4(); 
CREATE TABLE metadata(document INTEGER, page INTEGER, UNIQUE(document, page)); 

tôi muốn để có thể truy vấn cho các tài liệu, hoặc cho các trang trong một tài liệu đưa ra:

SELECT DISTINCT document FROM metadata NATURAL JOIN data WHERE content MATCH 'foo'; 
SELECT page FROM metadata NATURAL JOIN data 
    WHERE document = 123 AND content MATCH 'foo'; 

Tôi nghĩ NATURAL JOIN yêu cầu tôi đảm bảo rằng các hàng được giữ đồng bộ, nhưng cách tốt nhất để làm điều đó là gì? Tôi có nên sử dụng khóa NGOẠI HỐI hay ràng buộc khác không? Một sub-select có thể tốt hơn là join?

Tôi muốn chèn một tài liệu và trang đã có trong cơ sở dữ liệu để ghi đè nội dung văn bản. Là có thể lập trình thông qua SQL hoặc tôi sẽ phải kiểm tra xem hàng đã tồn tại trong bảng thông tin?

Tôi cũng sẽ muốn XOÁ TỪ cả hai bảng cho một tài liệu nhất định - có cách nào để thực hiện điều này trong một câu lệnh không?

Tất cả lời khuyên đã được biết ơn, nhưng vì tôi là người mới sử dụng SQL, các mẫu mã đặc biệt được đánh giá cao!

Cập nhật: Hoàn toàn không rõ ràng cách tôi có thể tạo ràng buộc khóa ngoại tại đây. Nếu tôi chọn metadata như bảng cha (đó sẽ là sở thích của tôi, trong sự vắng mặt của một hạn chế hai chiều):

PRAGMA foreign_keys = ON; 
CREATE TABLE metadata (document INTEGER, page INTEGER); 
CREATE VIRTUAL TABLE data USING fts4(content TEXT, docid REFERENCES metadata); 

tôi nhận được Error: vtable constructor failed: data (gì ngạc nhiên, bởi vì docid là một bí danh cho rowid, nhưng dĩ nhiên tôi có thể không sử dụng cột khác vì tất cả các cột ngoại trừ rowid phải là TEXT).

Trong khi đó nếu tôi cố gắng theo chiều ngược lại:

PRAGMA foreign_keys = ON; 
CREATE VIRTUAL TABLE data USING fts4(); 
CREATE TABLE metadata (document INTEGER, page INTEGER, docid REFERENCES data); 

việc xây dựng bảng thành công, nhưng nếu tôi cố gắng:

INSERT INTO data (docid, content) VALUES (123, 'testing'); 
INSERT INTO metadata (docid, document, page) VALUES (123, 12, 23); 

tôi nhận được Error: foreign key mismatch.

+0

bạn có quản lý tạo các bảng ảo bằng các khóa ngoại không? – Maragues

+0

@Maragues Không, và bạn cũng không thể thực thi các ràng buộc giống nhau - xem câu trả lời của tôi bên dưới. Các bảng ảo AFAICT thực sự chỉ là các chương trình với các giao diện SQL. – hatfinch

Trả lời

6

Tóm lại, thật khó để thực thi tính nhất quán trong đó FTS3 có liên quan.

Bảng ảo SQLite không cho phép trình kích hoạt và bảng FTS3 bỏ qua các ràng buộc và mối quan hệ.

Điều tốt nhất tôi đã có thể làm cho đến nay như sau:

CREATE TABLE metadata (document INTEGER, page INTEGER, UNIQUE(document, page)); 
CREATE VIRTUAL TABLE data USING fts4(); 

CREATE VIEW whole AS SELECT metadata.rowid AS rowid, document, page, content 
    FROM metadata JOIN data ON metadata.rowid = data.rowid; 

CREATE TRIGGER whole_insert INSTEAD OF INSERT ON whole 
BEGIN 
    INSERT INTO metadata (document, page) VALUES (NEW.document, NEW.page); 
    INSERT INTO data (rowid, content) VALUES (last_insert_rowid(), NEW.content); 
END; 

CREATE TRIGGER whole_delete INSTEAD OF DELETE ON whole 
BEGIN 
    DELETE FROM metadata WHERE rowid = OLD.rowid; 
    DELETE FROM data WHERE rowid = OLD.rowid; 
END; 

Để thực thi nhất quán tôi có thể (với PRAGMA recursive_triggers = NO) tạo trình kích hoạt để nâng cao ngoại lệ đối với hoạt động trực tiếp trên các bảng metadatadata, nhưng đây có lẽ là quá mức cần thiết cho mục đích của tôi (tương tự như vậy, tôi không cần kích hoạt UPDATE cho bảng whole).

-1

Tôi nghĩ hầu hết các DBA đều đồng ý rằng nếu bạn đang sử dụng SQL, bạn nên tận dụng tất cả các khoa mà nó cung cấp.

Khóa ngoại là tuyến đường chung tôi muốn giới thiệu và chúng được ghi thành tài liệu here.

Nói chung với cơ sở dữ liệu SQL, bạn sẽ không bao giờ phải thực thi thủ công tính nhất quán theo cách thủ công. Đặc biệt trong trường hợp phù hợp tốt với một khóa ngoại như thế này.

Đối với trường hợp DELETE FROM, SQLite không hỗ trợ từ khóa "xếp tầng" như nói MS SQL, nhưng nó có trình kích hoạt cho phép bạn có hành vi này. Tài liệu về trình kích hoạt SQLite có thể được tìm thấy here.

Cuối cùng, tôi sẽ bỏ qua việc tham gia tự nhiên.

+1

Rõ ràng SQLite hiện hỗ trợ tầng DELETE, nhưng điều đó không được sử dụng nhiều vì tôi không thể có được ràng buộc khóa ngoài để làm việc (vui lòng xem phần cập nhật ở trên). P.S. Bạn có thể vui lòng xác nhận: khi bạn nói "bỏ qua tham gia tự nhiên", bạn có ý định sử dụng phụ chọn thay thế không? – hatfinch

+2

Bảng FTS không hỗ trợ khóa hoặc chỉ mục ngoại quốc thuộc bất kỳ loại nào khác ngoài 'docid' /' rowid' – Greyson

Các vấn đề liên quan