数据库被锁定在 Sqlite
Posted
技术标签:
【中文标题】数据库被锁定在 Sqlite【英文标题】:Database is locked in 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* ],您是否使用过其他一些查询并且它仍然保持打开状态? 显示详情时我正在打开数据库 【参考方案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 浏览器并从中进行任何更新时,请确保您已保存所有更改,否则会发生明智的锁定情况。
【讨论】:
以上是关于数据库被锁定在 Sqlite的主要内容,如果未能解决你的问题,请参考以下文章