Передача массива в SQLite где в предложении через FMDB?
можно ли передать массив в оператор SELECT ... WHERE ... IN через FMDB? Я попытался взорвать массив следующим образом:
NSArray *mergeIds; // An array with NSNumber Objects
NSString *mergeIdString = [mergeIds componentsJoinedByString:@","];
NSString *query = @"SELECT * FROM items WHERE last_merge_id IN (?)";
FMResultSet *result = [database executeQuery:query, mergeIdString];
это работает, только если в массиве есть ровно 1 объект, что заставляет меня полагать, что FMDB добавляет кавычки вокруг всей взорванной строки.
поэтому я попытался передать массив как метод FMDB:
NSArray *mergeIds; // An array with NSNumber Objects
NSString *query = @"SELECT * FROM items WHERE last_merge_id IN (?)";
FMResultSet *result = [database executeQuery:query, mergeIds];
который не работает вообще.
Я ничего не нашел об этом в README или образцах на странице GitHub FMDB.
Спасибо, Стефан
6 ответов
у меня была та же проблема, и я понял это, по крайней мере, для моего собственного приложения. Во-первых, структурируйте свой запрос так, чтобы количество вопросительных знаков соответствовало количеству данных в массиве:
NSString *getDataSql = @"SELECT * FROM data WHERE dataID IN (?, ?, ?)";
затем использовать executeQuery:withArgumentsInArray
звоните:
FMResultSet *results = [database executeQuery:getDataSql withArgumentsInArray:dataIDs];
в моем случае у меня был массив объектов NSString внутри NSArray с именем dataIDs. Я пробовал всевозможные вещи, чтобы заставить этот SQL-запрос работать, и, наконец, с помощью этой комбинации sql / function call я смог получить правильные результаты.
Ну, я думаю, я должен использовать executeQueryWithFormat
(что, согласно документации FMDB, не рекомендуется). Во всяком случае, вот мое решение:
NSArray *mergeIds; // An array of NSNumber Objects
NSString *mergeIdString = [mergeIds componentsJoinedByString:@","];
NSString *query = @"SELECT * FROM items WHERE last_merge_id IN (?)";
FMResultSet *res = [self.database executeQueryWithFormat:query, mergeIdString];
если ключи являются строками, я использую следующий код для создания команды SQL:
(предположим, что strArray-это NSArray, содержащий элементы NSString)
NSString * strComma = [strArray componentsJoinedByString:@"\", \""];
NSString * sql = [NSString stringWithFormat:@"SELECT * FROM tableName WHERE fieldName IN (\"%@\")", strComma];
обратите внимание: если какие-либо элементы в strArray потенциально могут содержать символы "двойной кавычки", вам нужно написать дополнительные коды (перед этими 2 строками), чтобы избежать их, написав 2 двойные кавычки.
добавление на Wayne Liu, если вы знаете, что строки не содержат одинарных или двойных кавычек, вы можете просто сделать:
NSString * delimitedString = [strArray componentsJoinedByString:@"','"];
NSString * sql = [NSString stringWithFormat:@"SELECT * FROM tableName WHERE fieldName IN ('%@')", delimitedString];
вот расширение Swift для FMDatabase, которое разбивает параметры запроса массива на несколько именованных параметров.
extension FMDatabase {
func executeQuery(query: String, params:[String: AnyObject]) -> FMResultSet? {
var q = query
var d = [String: AnyObject]()
for (key, val) in params {
if let arr = val as? [AnyObject] {
var r = [String]()
for var i = 0; i < arr.count; i++ {
let keyWithIndex = "\(key)_\(i)"
r.append(":\(keyWithIndex)")
d[keyWithIndex] = arr[i]
}
let replacement = ",".join(r)
q = q.stringByReplacingOccurrencesOfString(":\(key)", withString: "(\(replacement))", options: NSStringCompareOptions.LiteralSearch, range: nil)
}
else {
d[key] = val
}
}
return executeQuery(q, withParameterDictionary: d)
}
}
пример:
let sql = "SELECT * FROM things WHERE id IN :thing_ids"
let rs = db.executQuery(sql, params: ["thing_ids": [1, 2, 3]])