0

我为我的应用程序使用了 sqlite DB,我需要同时调用两个查询,但我给出错误:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“错误准备语句”

我每 10 秒运行一次计时器,用于在按钮事件后从数据库中选择行在数据库中插入行。

我的代码片段为:

viewWillAppear

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") ;

}

并在viewWillDisappear

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") ;
}

对于Inserting rows

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);

Selecting rows

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);

任何人都请帮我解决这个问题。

谢谢!

4

2 回答 2

1

您应该更改您的NSAssert语句以包含错误消息:

NSAssert1(0, @"error preparing statement: %s", sqlite3_errmsg(database));

一旦你这样做了,你应该得到一个有意义的回应,这将帮助你诊断问题。

如果不查看sqlite3_errmsg消息,则很难诊断问题。它可能像列名或表名中的拼写错误一样简单,也可能像未找到表一样复杂,因为创建时找不到数据库,因此创建了一个空白数据库(没有该表)。在我们看到错误消息之前很难说。


顺便说一句,您不应该使用 SQL 来构建您的 SQL,stringWithFormat因为您会面临 SQL 注入攻击,并且如果这些文本值中的任何一个带有撇号,也会出现问题。您应该使用?占位符而不是 printf 样式的格式化程序,然后通过sqlite3_bind_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

于 2013-07-30T07:28:08.863 回答
0

添加这两个方法并在插入和选择之前在insert方法中调用它们,

 - (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);
}
于 2013-07-30T07:26:15.400 回答