在iOS上使用sqlite3_bind_时,SQLite IN运算符不起作用

时间:2012-04-27 13:50:37

标签: objective-c sqlite

我有以下SQL语句:

const char* sqlStatement = "SELECT ((? - deal.latitude) * (? - deal.latitude) + (? - deal.longitude) * (? - deal.longitude)) AS distance, id, title, shop, latitude, longitude FROM deal WHERE (type = ?) AND category IN (?) AND tribe IN (?) ORDER BY distance LIMIT 20;";

// ...

sqlite3_bind_double(preparedStatement, 1, location.latitude);
sqlite3_bind_double(preparedStatement, 2, location.latitude);
sqlite3_bind_double(preparedStatement, 3, location.longitude);
sqlite3_bind_double(preparedStatement, 4, location.longitude);
sqlite3_bind_int(preparedStatement, 5, type);
sqlite3_bind_text(preparedStatement, 6, [categories UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(preparedStatement, 7, [tribes UTF8String], -1, SQLITE_TRANSIENT);

这里,第六个和第七个参数导致查询失败,我的意思是我的

中的块
while (sqlite3_step(preparedStatement) == SQLITE_ROW) {

未执行。类别和部落的构建如下:

NSArray* userCategories = [CategoryDataController getUserCategories];
NSMutableString* categories = [[NSMutableString alloc] init];

for (NSNumber *category in userCategories) {
    [categories appendString:[[NSString alloc] initWithFormat:@"%@, ", category]];
}
if ([categories length] > 0) {
    categories = (NSMutableString *)[categories substringToIndex:[categories length] - 2];
}

NSArray* userTribes = [TribeDataController getUserTribes];
NSMutableString* tribes = [[NSMutableString alloc] init];

for (NSNumber* tribe in userTribes) {
    [tribes appendString:[[NSString alloc] initWithFormat:@"%@, ", tribe]];
}
if ([tribes length] > 0)
    tribes = (NSMutableString *)[tribes substringToIndex:[tribes length] - 2];

userCategories和userTribes是NSNumber的数组,如果我记录部落和类别,我会得到格式良好的字符串,如下所示:

1, 2, 3, 4, 5

奇怪的是,使用sqlite3_bind_函数我构建查询如下:

NSString *sqlStatementNSString = [[NSString alloc] initWithFormat:@"SELECT ((%f - deal.latitude) * (%f - deal.latitude) + (%f - deal.longitude) * (%f - deal.longitude)) AS distance, id, title, shop, latitude, longitude FROM deal WHERE type = %d AND category IN (%@) AND tribe IN (%@) ORDER BY distance LIMIT 20;", location.latitude, location.latitude, location.longitude, location.longitude, type, categories, tribes];
const char *sqlStatement = [sqlStatementNSString UTF8String];

它有效!我做错了什么?先谢谢(拜托,对不起我的英文)。

1 个答案:

答案 0 :(得分:0)

我也搜索了这个问题的答案,似乎一般来说,预处理语句不支持IN运算符。您可以在此站点上找到各种解决方案。我的首选解决方案(从其中一个答案中获得)是准备一个在IN运算符列表中具有固定数量的插槽的语句:

SELECT * FROM db WHERE id IN (?, ?, ?, ?, ?, ?)

然后执行查询((n + 5)/ 6)次(在此示例中)并合并所有答案。如果您的插槽数少于插槽数,请使用NULL填充其余部分,或复制最后一个条目。希望优化器避免重复比较。

重用预准备语句可能比构建和运行自定义查询字符串更快(但确定配置文件!)