【问题标题】:Database is locked in Sqlite数据库被锁定在 Sqlite
【发布时间】:2011-08-05 05:44:49
【问题描述】:

我正在开发一个 iPhone 应用程序,当我将数据插入数据库时​​,我得到了"Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error while inserting data. 'database is locked''" Error. 代码是:

- (NSString *) getDBPath {        
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
        NSString *documentsDir = [paths objectAtIndex:0];
        return [documentsDir stringByAppendingPathComponent:@"Halal.sqlite"];
}

+ (void) finalizeStatements {

            if (database) sqlite3_close(database);
            if (deleteStmt) sqlite3_finalize(deleteStmt);
            if (addStmt) sqlite3_finalize(addStmt);
            if (detailStmt) sqlite3_finalize(detailStmt);
            if (updateStmt) sqlite3_finalize(updateStmt);
}

- (void) gettingData:(NSString *)dbPath {

            NSLog(@"Data base path is %@",dbPath);
            if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
            {
                const char *sql = "select * from Product";
                sqlite3_stmt *selectstmt;
                if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) 
                {
                    while(sqlite3_step(selectstmt) == SQLITE_ROW)
                    {
        [membersInfoDict setValue:[NSString stringWithUTF8String:(char*)sqlite3_column_text(selectstmt, 0)] forKey:@"ProductName"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] forKey:@"ProductBarcode"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] forKey:@"ProductImage"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] forKey:@"ProductIngredients"];
                        [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] forKey:@"ProductStatus"];


                        if(membersInfoDict)
                        {
                           [membersInfoArray addObject:membersInfoDict];
                           membersInfoDict = nil;
                        //  NSLog(@"Entered and return");
                            return;
                        }
                    }
                }            
            }

            else
                sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.

}


- (void) addRecord:(NSMutableDictionary *)recordDict
{
            if (sqlite3_close(database))
            {
                NSLog(@"Closed");
                NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
                NSString *documentsDir = [paths objectAtIndex:0];

                [self gettingData:[documentsDir stringByAppendingPathComponent:@"Halal.sqlite"]];                   
            }   
            else {
                NSLog(@"Not Closed");
            }               
            if(addStmt == nil) {
                const char *sql = "insert into Product(ProductName, ProductBarcode , ProductImage,ProductIngredients,ProductStatus ) Values(?,?,?,?,?)";
                if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
                    NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
            }

            sqlite3_bind_text(addStmt, 1, [[recordDict objectForKey:@"ProductName"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 2, [[recordDict objectForKey:@"ProductBarcode"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 3, [[recordDict objectForKey:@"ProductImage"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 4, [[recordDict objectForKey:@"ProductIngredients"] UTF8String], -1, SQLITE_TRANSIENT);
            sqlite3_bind_text(addStmt, 5, [[recordDict objectForKey:@"ProductStatus"] UTF8String], -1, SQLITE_TRANSIENT);


            if(SQLITE_DONE != sqlite3_step(addStmt))
                NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));
            else
            //SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
                rowID = sqlite3_last_insert_rowid(database);
            NSLog(@"last inserted rowId = %d",rowID);

            //Reset the add statement.
            sqlite3_reset(addStmt);
            //sqlite3_commit_hook();
            //sqlite3_commit_hook(addStmt,[NSString stringWithFormat:@"%d",rowID],database);

}

请给我解决方案。 非常感谢...

【问题讨论】:

  • 您在哪里打开 [ "database " sqlite3* ],您是否使用过其他一些查询并且它仍然保持打开状态?
  • 显示详情时我正在打开数据库

标签: iphone objective-c database sqlite


【解决方案1】:

您需要完成编译后的语句,然后在再次打开之前关闭数据库。

sqlite3_finalize(compiledStatement);
sqlite3_close(database);

【讨论】:

    【解决方案2】:

    按照你修改后的方法搜索评论//ADD THIS LINE TO YOUR CODE

    - (void) gettingData:(NSString *)dbPath {
        NSLog(@"Data base path is %@",dbPath);
        if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
        {
            const char *sql = "select * from Product";
            sqlite3_stmt *selectstmt;
            if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
            {
                while(sqlite3_step(selectstmt) == SQLITE_ROW)
                {
                    [membersInfoDict setValue:[NSString stringWithUTF8String:(char*)sqlite3_column_text(selectstmt, 0)] forKey:@"ProductName"];
                    [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] forKey:@"ProductBarcode"];
                    [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] forKey:@"ProductImage"];
                    [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] forKey:@"ProductIngredients"];
                    [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] forKey:@"ProductStatus"];
    
                    if(membersInfoDict)
                    {
                        [membersInfoArray addObject:membersInfoDict];
                        membersInfoDict = nil;
                        //  NSLog(@"Entered and return");
                        sqlite3_close(database);
                        return;
                    }
                }
            }
            //ADD THIS LINE TO YOUR CODE
            sqlite3_finalize(selectstmt);
        }        
        else
            sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
    }
    

    【讨论】:

    • 如果 (membersInfoDict) 您在不释放数据库的情况下返回。你应该在那里包含一个 sqlite3_close。
    • @Vincent 每次访问数据库时都应该关闭它吗?另外,我使用一种方法 [self openDB] 打开数据库。将功能分开还是应该在同一个地方做所有事情是否重要。好像没关系。
    • 不,不必每次都关闭数据库。但是,尽可能短地打开和/或锁定 dbase 是一种“好的编程”。
    • 添加 sqlite3_finalize(selectstmt); sqlite3_close(数据库)正上方;为我工作。
    【解决方案3】:

    以上答案是正确的,但是如果我们在模拟器上工作或调试,数据库会显示锁定错误。

    案例一:

    在这里,我将解释一个将数据插入表中的场景。并且该数据库正在通过任何数据库浏览器访问并从模拟器访问。

    现在,当您通过模拟器处理应用程序时,您将数据保存在数据库数据中。现在,如果您使用任何浏览器访问该数据库中的数据,并且如果您在浏览器中触发任何更新命令并尝试更新任何行,它将将该行更新到表中。 (现在,当我们尝试从表中删除任何内容时,它总是显示一条消息,在浏览器中授予只读权限等)。

    现在进入模拟器,或者如果您再次运行该应用程序 当您尝试在该表中插入任何数据时,它总是显示错误“数据库已锁定”,因为权限是只读的,我们调整了这些权限。现在,如果您尝试更改答案中提到的命令,您将永远感到悲伤。它总是显示数据库被锁定的错误(我尝试了几次解决这个问题,但每次都失败了)。

    解决这种情况的唯一方法是:从模拟器中删除应用程序并重新安装。 并避免从浏览器更新/插入任何行。

    另一个答案是: 案例2:

    当您使用 sqlite 浏览器并从中进行任何更新时,请确保您已保存所有更改,否则会发生明智的锁定情况。

    【讨论】:

      猜你喜欢
      • 2011-10-30
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多