sqlite fts5表必须显式启用而非默认支持,需在编译时加-dsqlite_enable_fts5或运行时用pragma compile_options验证enable_fts5存在,否则create virtual table ... using fts5会报错no such module。

SQLite FTS5 表必须显式启用,不是默认支持
SQLite 的全文搜索能力依赖 FTS(Full-Text Search)扩展,而 FTS5 是目前推荐的版本。它不会自动加载,必须在编译时启用或运行时确认支持。C++ 程序链接 SQLite 库后,如果 sqlite3_compileoption_get 返回中不含 ENABLE_FTS5,CREATE VIRTUAL TABLE ... USING fts5 会直接报错 no such module: fts5。
实操建议:
- 用
sqlite3_compileoption_get(0, &i)循环检查编译选项,确认存在ENABLE_FTS5 - 若使用预编译二进制(如系统包管理器安装的 libsqlite3),优先查文档或运行
sqlite3 -version -cmd "PRAGMA compile_options;"验证 - 自己编译时需加
-DSQLITE_ENABLE_FTS5,否则即使代码写了 FTS5 也会失败
创建 FTS5 表时字段定义影响查询行为
FTS5 表的列声明方式直接影响 MATCH 查询能否命中内容。比如声明为 content TEXT 但未指定 content= 参数,该列默认不参与索引;而 title TEXT, body TEXT 这样并列声明,会自动全部加入全文索引。
实操建议:
- 避免写
CREATE VIRTUAL TABLE doc USING fts5(content)—— 这里content是列名,不是配置项;正确写法是CREATE VIRTUAL TABLE doc USING fts5(title, body) - 若想让某列仅存储不索引,用
UNINDEXED:例如CREATE VIRTUAL TABLE doc USING fts5(title, body, id UNINDEXED) - 需要前缀匹配(如
prefix=(2,3))必须在建表时指定,之后无法 ALTER,且会增加索引体积
C++ 绑定参数时 MATCH 查询不能用 ? 占位符直接拼接
MATCH 右侧是一个特殊表达式,不是普通字符串值。如果用 sqlite3_bind_text(stmt, 1, query.c_str(), -1, SQLITE_STATIC) 绑定到 ?,SQLite 会把它当作文本字面量而非查询语法,导致无结果或报错 malformed MATCH expression。
实操建议:
- 必须用字符串拼接构造完整 SQL,例如:
"SELECT * FROM doc WHERE doc MATCH '" + escape_fts_query(query) + "'" - 手动实现
escape_fts_query:对单引号'转义为'',对双引号"和反斜杠\视 FTS5 tokenizer 而定(默认 unicode61 不要求转义,但通配符*、短语引号"需保留原意) - 不要试图用
sqlite3_prepare_v2+bind处理整个 MATCH 表达式 —— 它不接受参数化
fts5 排序和高亮需额外函数,不是 SELECT * 自带
FTS5 本身不提供高亮或排名函数,highlight() 和 snippet() 是辅助函数,需确保它们可用(通常随 FTS5 一起编译)。直接 SELECT highlight(doc, 1, '<b>', '</b>') 会报错 no such function: highlight,除非确认 SQLite 启用了这些扩展。
实操建议:
- 检查函数是否存在:执行
SELECT sqlite_version(), (SELECT 1 FROM pragma_function_list WHERE name = 'highlight'); -
highlight(tbl, colidx, pre, post)中colidx从 0 开始,对应建表时列顺序;snippet()第 2–4 参数是前/中/后标记,第 5 参数是返回片段数 - 排序推荐用
rank或bm25():例如SELECT * FROM doc WHERE doc MATCH 'hello' ORDER BY bm25(doc) LIMIT 10,注意bm25()必须出现在 SELECT 列表或 ORDER BY 中,不能只在 WHERE 里
FTS5 的 rank 函数行为和权重配置容易被忽略,同一查询在不同表结构下排序结果可能差异很大,调试时最好先用 SELECT *, bm25(doc) FROM doc WHERE doc MATCH 'x' 看原始分值。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











