如何从SQLite数据库中检索值

时间:2014-02-06 15:47:53

标签: ios objective-c sqlite

我正在尝试从我的数据库中获取数据但我遇到了一些问题。

这是我的代码:

NSString *action=[[NSString alloc]init];
NSString *queryStatement = [NSString stringWithFormat:@"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = '%@'", symbol];

// Prepare the query for execution
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [queryStatement UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
    // Create a new address from the found row
    while (sqlite3_step(statement) == SQLITE_ROW) {
        action = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]; // fails on this line
    }
    sqlite3_finalize(statement);

    return action;
}

(参数符号来自外部)

当我运行此功能时,调用stringWithUTF8String且结果为sqlite3_column_text的行就失败了。

2 个答案:

答案 0 :(得分:2)

您可能希望以NSMutableArray

收集结果
NSMutableArray *action = [[NSMutableArray alloc] init];
...

while (sqlite3_step(statement) == SQLITE_ROW) {
     [action addObject:[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]];
}

...

然后您可以看到以后收集的内容:

for (NSString *s in action) {
    NSLog(@"%@", s);
}

编辑正如@ Rob的回答所指出的那样,第一列是0,而不是1

答案 1 :(得分:0)

在致电sqlite3_column_text时,您使用的是索引1,但它需要一个从零开始的索引。使用0代替1。请参阅SQLite sqlite_column_XXX documentation,其中包含:

  

结果集的最左列具有索引0。


顺便说一句,由于stringWithUTF8String如果您传递NULL值,则会引发异常,因此如果sqlite3_column_text不是NULL,则检查结果通常会更安全,否则优雅地处理错误。此外,您可能需要检查sqlite3_stepsqlite3_prepare_v2错误,例如:

NSString *queryStatement = [NSString stringWithFormat:@"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = '%@'", symbol];  // note, it can be dangerous to use `stringWithFormat` to build SQL; better to use `?` placeholders in your SQL and then use `sqlite3_bind_text` to bind the `symbol` value with the `?` placeholder

if (sqlite3_prepare_v2(database, [queryStatement UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
    int rc;
    while ((rc = sqlite3_step(statement)) == SQLITE_ROW) {
        const unsigned char *value = sqlite3_column_text(statement, 0);  // use zero

        if (value) {
            NSString *action = [NSString stringWithUTF8String:(const char *)value];

            // now do whatever you want with `action`, e.g. add it to an array or what
        } else {
            // handle the error (or NULL value) gracefully here
        }

        // make sure to check for errors in `sqlite3_step`

        if (rc != SQLITE_DONE)
        {
            NSLog(@"%s: sqlite3_step failed: %s", __FUNCTION__, sqlite3_errmsg(database));
        }
    }
}
else
{
    NSLog(@"%s: sqlite3_prepare_v2 failed: %s", __FUNCTION__, sqlite3_errmsg(database));
}

顺便说一句,如上所述,正确执行所有错误检查有点麻烦。这是FMDB可能有用的地方,将上述内容简化为(其中db是已打开的FMDatabase个对象):

FMResultSet *rs = [db executeQuery:@"SELECT ACTIONNAME FROM ACTIONS WHERE ACTIONSYMBOL = ?", symbol];
if (!rs) {
    NSLog(@"%s: executeQuery failed: %@", __FUNCTION__, [db lastErrorMessage]);
    return;
}

while ([rs next]) {
    NSString *action = [rs stringForColumnIndex:0];

    // do whatever you want with `action` here
}

[rs close];

如果您使用?占位符(而不是使用stringWithFormat来构建您的SQL,这很危险)使用FMDB的好处更具吸引力。