【问题标题】:SQLite FTS4 external content using view without column names使用不带列名的视图的 SQLite FTS4 外部内容
【发布时间】:2016-10-04 00:02:52
【问题描述】:

我正在使用 FTS4sqlite 3.8.10,我正在尝试设置这样的架构:

CREATE TABLE Test (name TEXT);
CREATE VIEW TestView as SELECT name FROM Test;
CREATE VIRTUAL TABLE TestFTS using FTS4(content="TestView", name);

在这个玩具示例中,我有一个简单的表 Test 和一个视图 TestView,它等效于该表。我从视图中创建了一个FTS4 索引TestFTS

然后我填充一些数据如下:

INSERT INTO Test VALUES ('bob');
INSERT INTO Test VALUES ('bill');
INSERT INTO Test VALUES ('jane');
INSERT INTO TestFTS(TestFTS) VALUES ('rebuild');

到目前为止一切顺利。现在我想查询我的数据,例如:

SELECT name FROM TestFTS WHERE name MATCH "b*";

这应该返回两行:

鲍勃

账单

相反,它返回单行并且该行是空白的。如果我从TestFTS 表中查询所有数据,那么我可以看到这些值,但是如果我不能进行MATCH 类型查询,显然它并没有多大用处:

SELECT name FROM TestFTS;

鲍勃

账单

知道为什么MATCH 对外部内容VIEWs 没有列名的查询时,SQLite 没有返回数据,甚至没有返回正确的行数吗?

====

更新:我已尝试将 sqlite 3.13 与命名列视图一起使用,但遇到了同样的问题。

【问题讨论】:

    标签: sqlite fts4


    【解决方案1】:

    视图需要一个名为 rowid 的列。身份证不够用。 注意:SQLite 网站上External Content Tables 的示例具有误导性:

    INSERT INTO t3(docid, b, c) SELECT id, b, c FROM t2;
    

    使用和 id 列适用于普通表,但不适用于视图。您需要改用 rowid:

    INSERT INTO t3(docid, b, c) SELECT id rowid, b, c FROM t2;
    

    基于 SQLite 文档示例的带有 SQLite 3.11 的 Linux 的完整控制台示例。

    使用视图不起作用:

    $ sqlite3 does_not_work.db;
    SQLite version 3.11.0 2016-02-15 17:29:24
    Enter ".help" for usage hints.
    sqlite> CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c);
    sqlite> CREATE VIEW t2_v AS SELECT id, a, b, c FROM t2;
    sqlite> CREATE VIRTUAL TABLE t3 USING fts4(content="t2_v", b, c);
    sqlite> INSERT INTO t2 VALUES(2, 'a b', 'c d', 'e f');
    sqlite> INSERT INTO t2 VALUES(3, 'g h', 'i j', 'k l');
    sqlite> INSERT INTO t3(docid, b, c) SELECT id, b, c FROM t2_v;
    sqlite> SELECT * FROM t3 WHERE t3 MATCH 'k';
    |
    sqlite> .exit
    

    但是在创建视图时为 id 设置一个 rowid 的列别名是可行的:

    sqlite3 works.db;
    SQLite version 3.11.0 2016-02-15 17:29:24
    Enter ".help" for usage hints.
    sqlite> CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c);
    sqlite> CREATE VIEW t2_v AS SELECT id rowid, a, b, c FROM t2;
    sqlite> CREATE VIRTUAL TABLE t3 USING fts4(content="t2_v", b, c);
    sqlite> INSERT INTO t2 VALUES(2, 'a b', 'c d', 'e f');
    sqlite> INSERT INTO t2 VALUES(3, 'g h', 'i j', 'k l');
    sqlite> INSERT INTO t3(docid, b, c) SELECT rowid, b, c FROM t2_v;
    sqlite> SELECT * FROM t3 WHERE t3 MATCH 'k';
    i j|k l
    sqlite> 
    

    不过,使用普通表格也可以:

    $ sqlite3 also_works.db;
    SQLite version 3.11.0 2016-02-15 17:29:24
    Enter ".help" for usage hints.
    sqlite> CREATE TABLE t2(id INTEGER PRIMARY KEY, a, b, c);
    sqlite> CREATE VIRTUAL TABLE t3 USING fts4(content="t2", b, c);
    sqlite> INSERT INTO t2 VALUES(2, 'a b', 'c d', 'e f');
    sqlite> INSERT INTO t2 VALUES(3, 'g h', 'i j', 'k l');
    sqlite> INSERT INTO t3(docid, b, c) SELECT id, b, c FROM t2;
    sqlite> SELECT * FROM t3 WHERE t3 MATCH 'k';
    i j|k l
    sqlite> 
    

    【讨论】:

      【解决方案2】:

      documentation 说:

      当用户对 FTS 表的查询需要 docid 以外的列值时,FTS 会尝试从内容表中 rowid 值等于当前 FTS docid 的行的对应列中读取请求的值。

      因此,视图必须包含一个名为 rowid 的唯一列,该列对应于 FTS 表的 docid

      【讨论】:

      • 注意:如果您使用的外部内容表不是基于视图,而是基于普通表,则名为 id 的列就足够了(正如 SQLi 上的示例所给出的那样
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多