Iphone iOS:Sqlite数据库错误:由于未捕获异常而终止应用程序';n内部一致性异常';,原因:';准备语句时出错';
我在应用程序中使用了sqlite DB,我需要同时调用两个查询,但我给出的错误是:由于未捕获的异常“nsInternalInconsistencException”终止应用程序,原因是:“准备语句时出错” 我每10秒运行一次计时器,用于在按钮事件后从DB选择行和在DB中插入行 我的代码片段为: 在Iphone iOS:Sqlite数据库错误:由于未捕获异常而终止应用程序';n内部一致性异常';,原因:';准备语句时出错';,iphone,ios,error-handling,sqlite,compiler-errors,Iphone,Ios,Error Handling,Sqlite,Compiler Errors,我在应用程序中使用了sqlite DB,我需要同时调用两个查询,但我给出的错误是:由于未捕获的异常“nsInternalInconsistencException”终止应用程序,原因是:“准备语句时出错” 我每10秒运行一次计时器,用于在按钮事件后从DB选择行和在DB中插入行 我的代码片段为: 在视图中,将出现: int result2 = sqlite3_open([dbPath UTF8String], &database); if (result2 != SQLITE_OK) {
视图中,将出现:
int result2 = sqlite3_open([dbPath UTF8String], &database);
if (result2 != SQLITE_OK) {
NSLog(@"Failure in connecting to the database with result %d",result2);
}
else {
NSLog(@ "Succesfully opened connection to DB") ;
}
int result = sqlite3_close(database);
if (result != SQLITE_OK){
NSLog(@"Failure in closing connection to database. Result %d",result);
}
else {
NSLog(@"Successfully closed DB connection") ;
}
并且在视图中将消失
:
int result2 = sqlite3_open([dbPath UTF8String], &database);
if (result2 != SQLITE_OK) {
NSLog(@"Failure in connecting to the database with result %d",result2);
}
else {
NSLog(@ "Succesfully opened connection to DB") ;
}
int result = sqlite3_close(database);
if (result != SQLITE_OK){
NSLog(@"Failure in closing connection to database. Result %d",result);
}
else {
NSLog(@"Successfully closed DB connection") ;
}
对于插入行的:
NSString *queryInsert = [NSString stringWithFormat: @"insert into mail_snoozlist (msgBody,msgSubject, msgSender,msgTo,msgDate,snoozTime) values('%@','%@','%@','%@','%@','%@')",strBody,msgSub,msgFrom,msgTo,strMsgDate,stringFromDate];
NSLog(@"queryInsert:%@",queryInsert);
const char *sql = [queryInsert UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_step(statement);
sqlite3_reset(statement);
} else {
NSAssert1(0,@"error preparing statement",sqlite3_errmsg(database));
return;
}
sqlite3_finalize(statement);
NSString *querySQL2 = [NSString stringWithFormat: @"Select * from mail_snoozlist WHERE snoozTime = '%@'",_snoozTime];
NSLog(@"querySql:%@",querySQL2);
if (sqlite3_prepare_v2(database, [querySQL2 UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
Message *obj = [[Message alloc] init];
NSString *msgBody=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
obj.msgBody= msgBody;
NSString *msgSub=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
obj.msgSub= msgSub;
NSString *msgSender=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
obj.msgFrom= msgSender;
NSString *msgTo=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
obj.msgTo= msgTo;
NSString *msgDate=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
obj.msgDate= msgDate;
[listOfItems addObject:obj];
[self.tableView reloadData];
}
sqlite3_reset(statement);
sqlite3_finalize(statement);
对于选择行
:
NSString *queryInsert = [NSString stringWithFormat: @"insert into mail_snoozlist (msgBody,msgSubject, msgSender,msgTo,msgDate,snoozTime) values('%@','%@','%@','%@','%@','%@')",strBody,msgSub,msgFrom,msgTo,strMsgDate,stringFromDate];
NSLog(@"queryInsert:%@",queryInsert);
const char *sql = [queryInsert UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_step(statement);
sqlite3_reset(statement);
} else {
NSAssert1(0,@"error preparing statement",sqlite3_errmsg(database));
return;
}
sqlite3_finalize(statement);
NSString *querySQL2 = [NSString stringWithFormat: @"Select * from mail_snoozlist WHERE snoozTime = '%@'",_snoozTime];
NSLog(@"querySql:%@",querySQL2);
if (sqlite3_prepare_v2(database, [querySQL2 UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
Message *obj = [[Message alloc] init];
NSString *msgBody=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
obj.msgBody= msgBody;
NSString *msgSub=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
obj.msgSub= msgSub;
NSString *msgSender=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
obj.msgFrom= msgSender;
NSString *msgTo=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
obj.msgTo= msgTo;
NSString *msgDate=[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
obj.msgDate= msgDate;
[listOfItems addObject:obj];
[self.tableView reloadData];
}
sqlite3_reset(statement);
sqlite3_finalize(statement);
请任何人帮我解决这个问题
谢谢 添加这两个方法,并在插入和选择之前在insert method中调用它们
- (void) createEditableCopyOfDatabaseIfNeeded
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"dbname.sqlite"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
//{
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"dbname.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
// }
if (!success)
{
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
- (void)initializeDatabase
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"dbname.sqlite"];
sqlite3_open([path UTF8String], &database);
}
您应该更改NSAssert
语句以包含错误消息:
NSAssert1(0, @"error preparing statement: %s", sqlite3_errmsg(database));
一旦你这样做了,你应该得到一个有意义的回答,这将帮助你诊断问题
如果不查看sqlite3\u errmsg
消息,就很难诊断问题。它可以简单到列名或表名中的输入错误,也可以复杂到无法找到表,因为创建数据库时找不到该表,所以创建了一个空白数据库(没有该表)。在看到错误消息之前很难说
顺便说一句,您不应该使用stringWithFormat
构建SQL,因为您会受到SQL注入攻击,并且如果这些文本值中有任何一个带有撇号,您也会遇到问题。您应该使用?
占位符而不是printf样式的格式化程序,然后使用sqlite3\u bind\u text
调用将值绑定到这些列:
NSString *queryInsert = @"insert into mail_snoozlist (msgBody,msgSubject, msgSender,msgTo,msgDate,snoozTime) values(?, ?, ?, ?, ?, ?)";
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) != SQLITE_OK) {
NSAssert1(0,@"error preparing statement: %s",sqlite3_errmsg(database));
return;
}
// for these 6 sqlite3_bind function calls, if any of these strings can be `nil`, then you'd
// want to call sqlite3_bind_null if that's the case, rather than sqlite3_bind_text
if (sqlite3_bind_text(statement, 1, [strBody UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 1: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_bind_text(statement, 2, [msgSub UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 2: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_bind_text(statement, 3, [msgFrom UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 3: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_bind_text(statement, 4, [msgTo UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 4: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_bind_text(statement, 5, [strMsgDate UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 5: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_bind_text(statement, 6, [stringFromDate UTF8String], -1, NULL) != SQLITE_OK) {
NSAssert1(0,@"error binding 6: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return;
}
if (sqlite3_step(statement) != SQLITE_DONE) {
NSAssert1(0,@"error stepping: %s",sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
我用insert
语句说明了这个问题,但是select
语句也应该这样做。对于调用,请使用这些行//[self-CreateEditableCopyOfDatabaseIfRequired];[自初始化数据库];谢谢你的回复。我在查询中做了一点更改,解决了这个问题:NSString*queryInsert=[NSString stringWithFormat:@“插入邮件休眠列表(msgBody、msgSubject、msgSender、msgTo、msgDate、snoozTime)值(“%s”、“s”、“s”、“s”、“s”、“s”、“strobdy UTF8String”、“msgObj.msgSub UTF8String]、[msgObj.msgFrom UTF8String]、[msgObj.msgTo UTF8String],[stringFromDate UTF8String],[stringFromDate UTF8String]];
谢谢您的回复。我已经通过查询中的一点更改解决了这个问题:NSString*queryInsert=[NSString stringWithFormat:@“插入邮件睡眠列表(msgBody,msgSubject,msgSender,msgTo,msgDate,snoozTime)值('%s','%s','%s','%s','%s','%s'),'%s'),[Strobdy UTString],[msgObj.msgSub UTF8String],[msgObj.msgFrom UTF8String],[msgObj.msgTo UTF8String],[strmssgdate UTF8String],[stringFromDate UTF8String]]
@Pankaj首先,你仍然应该将%s
添加到你的NSAssert1
行中,否则当你出错时,你将永远看不到sqlite3\u errmsg
。其次,在你的SQL中将%@
更改为%s
只是巧合地起作用,实际上并不能解决任何问题,只会使代码变得不那么清晰。第三,如果您提议的更改试图插入一个strobody
或一个msgSubject
中碰巧有撇号,那么您的代码仍然会崩溃。不要使用stringWithFormat
来构建SQL,而是使用sqlite3\u bind\u text
。另外,一个不诚实的用户可能会进行SQL注入攻击,例如,我添加了这个代码e、 但现在我得到了错误:由于未捕获的异常“nsinternalinconsistenceexception”而终止应用程序,原因是:“错误准备语句:库例程调用顺序错误”
。我没有得到任何错误绑定日志。@Pankaj现在您的断言报告了准确的SQLite错误消息:非常好。此错误,“库例程调用顺序不正确",表示您没有遵循。例如,如果您关闭了数据库而忽略了重新打开它,则可能会发生这种情况。我认为错误不在上面的代码中,而是在其他地方。请逐步检查代码,检查调用open、prepare、bind、Step、finalize和close的顺序。特别是在sqlite3\o处放置断点/日志pen
和sqlite3\u close
行。@Pankaj请参阅。