Передача массива в 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];

Я создал простое расширение FMDB для решения проблемы:

FMDB + InOperator на GitHub


вот расширение 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]])