SQLite WHERE 列 MATCH 参数绑定

Kir*_*ins 1 sqlite full-text-search fmdb ios swift

我有 FTS 表和查询,它匹配列包含“all”和“in”的所有行。

try db.executeQuery("SELECT * FROM table WHERE column MATCH '\"all\" AND \"in\"'", values: nil)
Run Code Online (Sandbox Code Playgroud)

如何使用参数绑定使其工作?所以我可以提供:

values: ["all", "in"]
Run Code Online (Sandbox Code Playgroud)

Gwe*_*oué 6

SQLite 使用纯字符串作为全文模式。因此,您必须根据您的多个单词为自己构建一个全文模式字符串,并将其作为一个 FMDB 参数提供,如下所示。

let words = ["all", "in"]
let pattern = words
    .map { "\"\($0)\"" } // wrap each word inside quotes
    .joined(separator: " AND ")
try db.executeQuery("SELECT * FROM table WHERE column MATCH ?", values: [pattern])
Run Code Online (Sandbox Code Playgroud)

请注意,并非所有模式都有效。请参阅全文索引查询语法。这意味着某些输入会触发 SQLite 错误。例如,如果单词来自文本字段,并且用户键入引号,例如"attack,那么您可能会构建""attack"SQLite 不会解析的无效模式(SQLite 错误 1: malformed MATCH expression)。

您可以尝试自己清理用户输入,但这在保留最大可用信息的同时很难做到。毕竟,应用程序用户通常不知道 SQLite 的微妙之处:如果他们碰巧输入了一个有趣的搜索字符串,就没有必要用空搜索结果来惩罚他们。

如果您需要执行模式清理,我建议您查看 GRDB,它是 FMDB 的替代品,非常支持全文搜索。它可以从用户输入构建安全模式:

let userInput = textField.text
let pattern = FTS3Pattern(matchingAllTokensIn: userInput)
let rows = try Row.fetchAll(db, "SELECT * FROM table WHERE column MATCH ?", arguments: [pattern])
Run Code Online (Sandbox Code Playgroud)

当用户键入 时"attackFTS3Pattern(matchingAllTokensIn:)将构建健全的attackFTS 模式而不是失败。GRDB 使用 SQLite 本身来执行清理,这意味着它非常可靠。

有关更多信息,请参阅GRDB 全文搜索文档