我在iOS 6 app for iPad中使用了这个sqlite3表:
CREATE TABLE notes(id INTEGER PRIMARY KEY, note TEXT, noteDate TEXT, wasUploaded INTEGER);
从sqlite3命令行开始,此查询有效:
sqlite> Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0;
1|Well|2012-10-04 22:46:23|0
在iOS iPad 6.0 Simulator上,每个查询都返回与上面完全相同的数据:
const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `id`=1";
const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `note`='Well'";
const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `noteDate`='2012-10-04 22:46:23'";
但是这个在命令行上工作正常的查询现在不返回任何数据:
const char *sqlStatement = "Select `id`,`note`,`noteDate`,`wasUploaded` FROM `notes` WHERE `wasUploaded`=0";
让我感到困惑。为什么最后一个查询不起作用?我是否需要将该列作为索引或其他内容?其他两个非索引列可以工作但不是这个。
没有错误。返回没有数据的最后一个查询给出了正常的返回代码101(sqlite3_step()已经完成执行),没有where子句的查询返回与其他三个查询相同的数据。
编辑:这是完整的代码
- (NSString *)getNotesToBeUploaded {
sqlite3 *stuDb;
NSString *thisNote;
NSMutableString *notes = [[NSMutableString alloc]init];
if (self.filePath == @"empty") {
[self setDatabaseFilePath];
}
if (sqlite3_open([self.filePath UTF8String], &stuDb) == SQLITE_OK)
{
// this is the query line that get changed to show stackoverflow the different results:
const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
sqlite3_stmt *compiledStatement;
int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
if ( nResult == SQLITE_OK)
{
int nret; // diagnostic used to watch return vaues when single stepping
while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
{
int id = sqlite3_column_int(compiledStatement, 0);
const unsigned char *note = sqlite3_column_text(compiledStatement, 1);
const unsigned char *noteDate = sqlite3_column_text(compiledStatement, 2);
int wu = sqlite3_column_int(compiledStatement, 4);
if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
{
thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
[notes appendString:thisNote];
}
}
} else {
sqlite3_finalize(compiledStatement);// prevent small memory leaks
sqlite3_close(stuDb);
thisNote =
[NSString stringWithFormat:@"prepare failed with status:%d in %s at line %d path was %@,0,0\n",nResult,__FILE__,__LINE__,self.filePath];
[notes appendString:thisNote];
[notes appendString:@"\n"];
return (NSString *)notes;
}
sqlite3_finalize(compiledStatement);
sqlite3_close(stuDb);
}
答案 0 :(得分:3)
您是否正在查看sqlite3
来电的退货代码?而且,如果您未获得SQLITE_OK
或SQLITE_ROW
,则应检查sqlite3_errmsg
结果以诊断正在发生的情况。如果您希望我们帮助您,您真的应该分享您的代码。
但是,第一次使用iOS SQLite应用程序时最常见的问题是
未能将数据库包含在您应用的捆绑包中。检查目标设置,确保已将数据库包含在Build Phases
中。您还可以通过查看~/Library/Application Support/iPhone Simulator
文件夹中模拟器中的应用程序包来确认这一点。如果您想这样做,如果您没有在终端命令行界面中输入~/Library
,则可能需要取消隐藏chflags no hidden ~/Library
文件夹。
如果您计划从应用程序更新数据库,则在尝试开始使用之前,无法先将数据库从软件包复制到Documents
文件夹。
使用sqlite3_open
并将成功的返回代码解释为数据库已成功打开的证据...但如果找不到数据库,sqlite3_open
函数会恼人地创建一个新的空白数据库...我总是建议人们使用sqlite3_open_v2
代替,如果没有找到,那么你可以省略参数来创建一个空数据库。
当然,也可能存在大量与代码相关的问题(调用函数的顺序,无法检查返回代码等)。如果没有看到代码,就无法进一步评论。
我觉得有必要分享我的最终SQLite编程建议,值得查看FMDB Objective-C SQLite wrapper library,这极大地简化了iOS中的SQLite编程。
<强>更新强>
看了你的代码,它看起来很好。我刚刚运行它(仅调整到NSLog
而不是附加说明):
- (void)test2
{
sqlite3 *stuDb;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *databaseName = [documentsDirectory stringByAppendingPathComponent:@"test.db"];
if (sqlite3_open([databaseName UTF8String], &stuDb) == SQLITE_OK)
{
// this is the query line that get changed to show stackoverflow the different results:
const char *sqlStatement = "Select `id`,`note`,`noteDate` FROM notes WHERE `wasUploaded`=0";
sqlite3_stmt *compiledStatement;
int nResult = sqlite3_prepare_v2(stuDb, sqlStatement, -1, &compiledStatement, NULL);
if ( nResult == SQLITE_OK)
{
int nret; // diagnostic used to watch return vaues when single stepping
while ((nret = sqlite3_step(compiledStatement)) == SQLITE_ROW)
{
int id = sqlite3_column_int(compiledStatement, 0);
const unsigned char *note = sqlite3_column_text(compiledStatement, 1);
const unsigned char *noteDate = sqlite3_column_text(compiledStatement, 2);
int wu = sqlite3_column_int(compiledStatement, 4);
if (strlen((const char *)note) > 0 && strlen((const char *)noteDate) > 0)
{
// thisNote = [NSString stringWithFormat:@"%d,%s,%s,%d\n",id, noteDate, note, wu];
// [notes appendString:thisNote];
NSLog(@"%d,%s,%s,%d\n",id, noteDate, note, wu);
}
}
} else {
//sqlite3_finalize(compiledStatement);// prevent small memory leaks, not needed if the prepare failed
sqlite3_close(stuDb);
NSLog(@"prepare failed with error %s", sqlite3_errmsg(stuDb));
return;
}
sqlite3_finalize(compiledStatement);
sqlite3_close(stuDb);
}
}
我得到了结果:
2012-10-05 15:44:06.075 test8[1574:c07] 1,2012-10-05 19:43:37,ABC,0
2012-10-05 15:44:06.076 test8[1574:c07] 2,2012-10-05 19:43:46,XYZ,0
所以问题必须在数据库本身。从你上次的评论来看,听起来重建数据库就是为你做的。那很好。