【问题标题】:iOS SQLite SELECT with UTF 8 characters带有 UTF 8 个字符的 iOS SQLite SELECT
【发布时间】:2015-05-23 23:37:59
【问题描述】:

我一直在阅读与 SQlite 编码相关的所有问题,但都没有成功,所以我会尝试询问我的具体情况。

我有一个预填充了 SQLite 数据库的 iOS 应用。 这个 SQLite 是从 MySQL 数据库转换而来的。 SQLite 和 MySQL 数据库都有 UTF8 编码(转换过程将默认的 sqlite 编码设置为 UTF8)

如果我用 Firefox SQlite Manager 打开我的 sqlite 数据库,我可以毫无问题地读取所有内容,并且所有 UTF8 字符都正确显示,所以我猜一切都正确转换了。

但是,当我尝试执行带有 UTF8 字符的选择时,查询失败。

这是我执行查询的方法:

- (NSArray *)performQuery:(NSString *)query
{
    static sqlite3 *db;
    sqlite3_stmt *resultado;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"mydatabase.sqlite"];
    const char *dbpath = [writableDBPath UTF8String];
    if (sqlite3_open(dbpath, &db) == SQLITE_OK)
    {
        printf("%s\n", [query UTF8String]);
        int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
        if (codigo == SQLITE_OK)
        {
            NSMutableArray *result = [NSMutableArray array];
            while (sqlite3_step(resultado) == SQLITE_ROW)
            {
                NSMutableArray *row = [NSMutableArray array];
                for (int i = 0; i < sqlite3_column_count(resultado); i++)
                {
                    int colType = sqlite3_column_type(resultado, i);
                    id value;
                    if (colType == SQLITE_TEXT)
                    {
                        value = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(resultado, i)];
                        if ([value isEqualToString:@"(null)"] || [value isEqualToString:@""] || (value == nil) || [value isKindOfClass:[NSNull class]])
                        {
                            value = @"";
                        }
                    }
                    else if (colType == SQLITE_INTEGER)
                    {
                        int col = sqlite3_column_int(resultado, i);
                        value = [NSNumber numberWithInt:col];
                    }
                    else if (colType == SQLITE_FLOAT)
                    {
                        double col = sqlite3_column_double(resultado, i);
                        value = [NSNumber numberWithDouble:col];
                    }
                    else if (colType == SQLITE_NULL)
                    {
                        value = [NSNull null];
                    }
                    else
                    {
                        NSLog(@"ERROR: DataBase - performQuery - Campo desconocido");
                    }
                    [row addObject:value];
                }
                [result addObject:row];
                row = nil;
            }
            sqlite3_finalize(resultado);
            sqlite3_close(db);
            resultado = nil;
            return result;
        }
        else
        {
            NSLog(@"ERROR [%d](%s): %@", codigo, sqlite3_errmsg(db), query);
        }
    }
    else
    {
        NSLog(@"ERROR: No se pudo abrir la base de datos");
    }
    sqlite3_close(db);
    db = nil;
    resultado = nil;
    return nil;
}

这就是我调用 performQuery 的方法:

- (int) getIdForItem:(NSString *)item
{
    NSString *query = [NSString stringWithFormat:@"SELECT item_id FROM table_items WHERE item_name=\"%@\"", item];
    NSLog(@"QUERY:\n%@", query);
    NSArray *answer = [self performQuery:query];
    if([answer count] > 0)
        return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
    return -1;
}

如果我打这个电话:

[self getIdForItem:@"Camión"];

这是输出:

QUERY:
SELECT item_id FROM table_items WHERE item_name="Camión"
SELECT item_id FROM table_items WHERE item_name="Camión"
ERROR [1](unrecognized token: ""Cami√≥n"): SELECT item_id FROM table_items WHERE item_name="Camión"

方法中产生此错误:

sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL)

那么,为什么 Camión 在 sqlite_prepare_v2 中被解释为 Cami√≥n?查询和 sqlite 数据库都使用 UTF8,所以我想我错过了一些东西......

【问题讨论】:

  • 不要使用stringWithFormat 构建查询。将值正确绑定到 SQL 语句中。
  • 完美!我已经改变了它,现在它可以工作了。我怎么能把这个解决方案归功于你?
  • 随时发布您自己的答案,说明您需要进行哪些更改才能使其正常工作。

标签: ios sqlite utf-8


【解决方案1】:

嗯,rmaddy 的解决方案非常适合我。我所做的是:

PerformQuery 几乎相同,它接收一个新参数:

- (NSArray *)performQuery:(NSString *)query withArgument:(NSString *)arg

在 sqlite3_prepare_v2 之后我进行了绑定:

    int codigo = sqlite3_prepare_v2(db,[query UTF8String],[query length],&resultado,NULL);
    if (codigo == SQLITE_OK)
    {
        sqlite3_bind_text(resultado, 1, [arg UTF8String], -1, SQLITE_TRANSIENT);

        NSMutableArray *result = [NSMutableArray array];
        while (sqlite3_step(resultado) == SQLITE_ROW)

最后,我这样称呼这个方法:

- (int) getIdForItem:(NSString *)item
{
    NSString *query = @"SELECT item_id FROM table_items WHERE item_name=?1";
    NSLog(@"QUERY:\n%@", query);
    NSArray *answer = [self performQuery:query];
    if([answer count] > 0)
        return [[[answer objectAtIndex:0] objectAtIndex:0] intValue];
    return -1;
}

【讨论】:

    猜你喜欢
    • 2016-06-09
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多