FMDB:SQLite语句ORDER BY错误地命令变音符号

时间:2014-12-19 18:41:56

标签: ios sqlite swift xcode6 fmdb

我是iOS开发的新手,我需要学习很多东西。它就像一座巨大的山峰,但多亏了你的帮助,我得到了一些地方;)

我已经启动了Xcode项目(Xcode版本6.1.1,Swift,iOS)并包含FMDB来运行SQLite查询。查询执行得很好,但是在以下语句中:

var resultSet: FMResultSet! = sharedInstance.database!.executeQuery("SELECT * FROM spesenValues ORDER BY country ASC", withArgumentsInArray: nil)

从我的角度来看,字母顺序是错误的,但我似乎并没有想出如何修复它。标准的A-Z字符被排序到我期望的位置,但任何包含变音符号的字符,例如, ÄÖÜ排在列表的最底部。

所以我期待的是:

Österreich...... Zypern

但我得到的是

Zypern ......Österreich

SQLite Order By places umlauts & speical chars at end我了解到,“iOS上的SQLite没有启用ICU”这一事实。

是否有一种简单的方法来配置FMDB以帮助我“正确”对其进行排序。如果这变成了一个非常愚蠢的问题,请提前感谢对不起

1 个答案:

答案 0 :(得分:4)

您可以定义自己的SQLite函数,使用CFStringTransform删除重音。使用FMDB 2.7:

db.makeFunctionNamed("unaccented", arguments: 1) { context, argc, argv in
    guard db.valueType(argv[0]) == .text || db.valueType(argv[0]) == .null else {
        db.resultError("Expected string parameter", context: context)
        return
    }

    if let string = db.valueString(argv[0])?.folding(options: .diacriticInsensitive, locale: nil) {
        db.resultString(string, context: context)
    } else {
        db.resultNull(context: context)
    }
}

然后,您可以在SQL中使用这个新的unaccented函数:

do {
    try db.executeQuery("SELECT * FROM spesenValues ORDER BY unaccented(country) ASC" values: nil) 

    while rs.next() {
        // do what you want with results
    }

    rs.close()
} else {
    NSLog("executeQuery error: %@", db.lastErrorMessage())
}

您建议您分别将“ä”,“ö”和“ü”替换为“ae”,“oe”和“ue”。这通常只使用正确的名称和地理名称(请参阅维基百科的German orthography条目),但如果您想这样做,请将您的自定义函数(我已重命名为“sortstring”)替换为适当的值:

db.makeFunctionNamed("sortstring", arguments: 1) { context, argc, argv in
    guard argc == 1 && (db.valueType(argv[0]) == .text || db.valueType(argv[0]) == .null) else {
        db.resultError("Expected string parameter", context: context)
        return
    }

    let replacements = ["ä": "ae", "ö": "oe", "ü": "ue", "ß": "ss"]

    var string = db.valueString(argv[0])!.lowercased()

    for (searchString, replacement) in replacements {
        string = string.replacingOccurrences(of: searchString, with: replacement)
    }

    db.resultString(string.folding(options: .diacriticInsensitive, locale: nil), context: context)
}

顺便说一下,由于你只是为了排序而使用它,你可能也希望将它转换为小写,以便大写值不与小写值分开。

但是这个想法是一样的,定义你想要排序的任何函数,然后你可以使用FMDB的makeFunctionNamed使它在SQLite中可用。