我有FTS表和查询,匹配列中包含“all”和“in”的所有行。
try db.executeQuery("SELECT * FROM table WHERE column MATCH '\"all\" AND \"in\"'", values: nil)
如何通过参数绑定实现此功能?所以我可以提供:
values: ["all", "in"]
答案 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。