将任意长度的数组绑定到SQLite查询

时间:2017-05-03 23:17:35

标签: swift sqlite fmdb

我需要使用编译时长度未知的参数数组运行SQLite查询(我使用的是FMDB,但如果需要,可以使用原生SQLite)。到目前为止,我已经根据数组长度手动将正确数量的绑定插入到字符串中:

func getBindString (_ arrayCount: Int) -> String {
    return [String](repeating: "?", count: arrayCount).joined(separator: ",")
}

let someArray = ["foo","bar"]
let sqlString = "delete from someTable where someColumn in (\(getBindString(someArray.count)))"
db.executeUpdate(sqlString, withArgumentsIn: someArray)
/* delete from someTable where someColumn in ('foo','bar') */

感觉真的很不优雅。有没有“适当的”处理方式?我在网上找到的所有东西都已经过时了几年,所有人都建议直接插值,这更糟糕。

1 个答案:

答案 0 :(得分:1)

我没有看到这个“不优雅”的东西。您正在使用基于字符串的语言(SQL),并且您可以非常巧妙地实时构建字符串。

你的代码与我写的不完全相同;我不喜欢不需要的字符串插值,这里不需要它,所以我会提出更像这样的东西(我也认为使用map而不是Array(repeating:)很好):

let someArray = ["foo","bar"]
let bindString = someArray.map{_ in "?"}.joined(separator: ",")
let sqlString = "delete from someTable where someColumn in (" + bindString + ")"

如果你必须多次形成像bindString这样的字符串,那么一定要把它变成一个实用函数。但后来我会把它写成Array的扩展名:

extension Array {
    var bindString : String {
        return "(" + self.map{_ in "?"}.joined(separator: ",") + ")"
    }
}

这样,你的字符串结构将如下所示:

let someArray = ["foo","bar"]
let sqlString = "delete from someTable where someColumn in " + someArray.bindString

但所有这些都是纯粹的风格调整;你正在做的事情中没有没有错误。