SQLite WHERE列MATCH参数绑定

时间:2017-10-19 12:44:14

标签: ios swift sqlite full-text-search fmdb

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

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

如何通过参数绑定实现此功能?所以我可以提供:

values: ["all", "in"]

1 个答案:

答案 0 :(得分:4)

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])

请注意并非所有模式都有效。请参阅Full-Text Index Queries Grammar。这意味着某些输入将触发SQLite错误。例如,如果单词来自文本字段,并且用户键入引号(如"attack中所示),那么您可以构建SQLite无法解析的无效模式""attack"(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])

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

有关详细信息,请参阅GRDB full-text search documentation