所以我对iOS开发很新,我的select函数出现问题。我创建了一个函数,应该接受一个select查询和表名并返回一个结果数组,其中每个数组条目都是一个带有一行结果的字典。不知怎的,我对列名的查询是删除我的columnNames
变量并返回疯狂的结果。我只想找出一种存储,访问,操作查询结果的简便方法
以下是将结果转换为数组的函数:
-(NSMutableArray *)selectQuery:(NSString*)query
table:(NSString*)table
{
NSMutableArray *returnArray = [NSMutableArray new];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSMutableArray *columnNames;
NSString *tableQuery = [NSString stringWithFormat:@"PRAGMA table_info('%@')", table];
if (sqlite3_prepare_v2(database, [tableQuery UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
[columnNames addObject:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, 1)]];
}
}
else
{
NSLog(@"Error preparing table query:");
NSLog(tableQuery);
}
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW)
{
NSMutableDictionary *temp= [NSMutableDictionary new];
for (int i = 0; i < [columnNames count]; i++)
{
[temp setObject:[NSString stringWithUTF8String:(const char*)sqlite3_column_text(statement, i)] forKey:columnNames[i]];
}
if (temp != nil)
{
[returnArray addObject:temp];
temp = nil;
}
}
sqlite3_reset(statement);
sqlite3_close(database);
}
else
{
NSLog(@"Error preparing select statement with query:");
NSLog(query);
}
}
else
{
NSLog(@"Could not open database");
}
return returnArray;
}
并继续致电
NSMutableArray *queryResults = [dbInstance selectQuery:[NSString stringWithFormat:@"SELECT gallons, mileage FROM fillups WHERE carId = \"%d\" ORDER BY date asc",
carId]
table:@"fillups"];
答案 0 :(得分:4)
您永远不会实例化columnNames
。因此,您尝试将列名添加到该数组将不会成功。要解决这个问题,当你声明它时,你也希望实例化可变数组对象:
NSMutableArray *columnNames = [NSMutableArray array];
与此问题无关,当您完成检索列名称时,在准备第二个语句之前,请不要忘记释放与第一个预准备语句关联的内存:
sqlite3_finalize(statement);
最后,当您完成检索第二个准备好的SQL语句而不是调用sqlite3_reset
时,您希望再次为该第二个预准备语句调用sqlite3_finalize
。当您想要将新值绑定到语句中的sqlite3_reset
占位符时,?
用于重置语句,这在此处不适用,因此不需要sqlite3_reset
。但是如果你不调用sqlite3_finalize
,你就不会释放与准备好的语句相关的内存。
顺便说一下,如果你想动态检索列名和列类型(无需PRAGMA table_info
),你可以这样做:
int rc;
if ((rc = sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL)) != SQLITE_OK) {
NSLog(@"select failed %d: %s", rc, sqlite3_errmsg(database));
}
NSMutableArray *returnArray = [NSMutableArray array];
NSInteger columnCount = sqlite3_column_count(statement);
id value;
while ((rc = sqlite3_step(statement)) == SQLITE_ROW) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (NSInteger i = 0; i < columnCount; i++) {
NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(statement, i)];
switch (sqlite3_column_type(statement, i)) {
case SQLITE_NULL:
value = [NSNull null];
break;
case SQLITE_TEXT:
value = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, i)];
break;
case SQLITE_INTEGER:
value = @(sqlite3_column_int64(statement, i));
break;
case SQLITE_FLOAT:
value = @(sqlite3_column_double(statement, i));
break;
case SQLITE_BLOB:
{
NSInteger length = sqlite3_column_bytes(statement, i);
const void *bytes = sqlite3_column_blob(statement, i);
value = [NSData dataWithBytes:bytes length:length];
break;
}
default:
NSLog(@"unknown column type");
value = [NSNull null];
break;
}
dictionary[columnName] = value;
}
[returnArray addObject:dictionary];
}
if (rc != SQLITE_DONE) {
NSLog(@"error returning results %d %s", rc, sqlite3_errmsg(database));
}
sqlite3_finalize(statement);