在这个项目中,我不允许使用第三方代码(即GRDB、Swift.sqlite),所以我需要直接使用swift的c- Package 器sqlite3函数。
我的SQL语句是可变的,基于某些标志。
var sql = "SELECT * FROM myTable WHERE "
sql += " colA = ? "
sql += " AND (colB > ? OR colB < ?) "
if flagC == true {
sql += " AND colC = ? "
}
sql += " AND colD = ? "
var stmt = OpaquePointer?
guard sqlite3_prepare_v2(dbPointer, sql, -1, &stmt, nil) == SQLITE_OK
else { print("error") }
guard sqlite3_bind_text(stmt, 1, (myVarA as NSString).utf8String, nil) == SQLITE_OK &&
sqlite3_bind_double(stmt, 2, myVarB, nil) == SQLITE_OK &&
sqlite3_bind_double(stmt, 3, myVarB1, nil) == SQLITE_OK
else { print("error") }
var nextPosition = 4
if flagC == true {
guard sqlite3_bind_int(stmt, nextPosition, myVarC, nil) == SQLITE_OK
else { print("error") }
nextPosition += 1
}
guard sqlite3_bind_double(stmt, nextPosition, myVarD, nil) == SQLITE_OK
else { print("error") }
while sqlite3_step(stmt) == SQLITE_ROW {
// deal with result
}
这是可行的,但是由于要中断guard
语句以容纳潜在的参数,因此感觉非常笨拙。
我能想到的使参数位置绑定“动态”的唯一方法是使用nextPosition
帮助变量。
“硬编码”绑定的位置感觉不对,有没有办法不用硬编码这些位置就解决这个问题?
1条答案
按热度按时间hlswsv351#
硬编码的数字索引和原始SQL字符串一样硬编码--不是更好,但也不是更差。我不会太担心它们。1,2,3?好的:这是第一,第二和第三个参数,这很清楚
我同意,如果不再需要
nextPosition
,我们可以增强您的示例代码。一个可能的改进是在构建SQL查询时将
flagC
测试移到末尾:您仍将使用硬编码索引(1,2,3,4),但不再需要
nextPosition
。另一种方法是使用命名参数:
您可以使用
sqlite3_bind_parameter_index
将参数名(:a
、:minB
等)转换为索引,而不是为参数(1、2、3、nextPosition
)提供数字索引。最后,另一种方法是尽早测试
flagC
,并完全独立地处理两个SQL请求,这将消除对nextPosition
的需求。