我使用下面的代码在数据库中插入数据。我正在插入aprox 15000记录但在245条记录之后它会抛出错误“无法打开数据库”
+(void)addGeoRegions:(const char *)query geoId:(int)geoId geoFatherId:(int)geoFatherId geoName:(NSString *)geoName
geoTypeRegionId:(NSString *)geoTypeRegionId geoZone:(int)geoZone
{
sqlite3_stmt *dataRows = nil;
@try {
if(sqlite3_open([[self getDBPath] UTF8String],&PatientDatabase) == SQLITE_OK)
{
if (sqlite3_prepare_v2(PatientDatabase, query, -1, &dataRows, NULL)!=SQLITE_OK)
{
NSAssert1(0,@"error while preparing %s",sqlite3_errmsg(PatientDatabase));
}
sqlite3_bind_int(dataRows, 1, geoId);
sqlite3_bind_int(dataRows, 2, geoFatherId);
sqlite3_bind_text(dataRows, 3, [geoName UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(dataRows, 4, [geoTypeRegionId UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(dataRows, 5, geoZone);
if (SQLITE_DONE!=sqlite3_step(dataRows))
{
char *err;
err=(char *) sqlite3_errmsg(PatientDatabase);
if (err)
sqlite3_free(err);
NSAssert1(0,@"error while inserting geo regions. %s",sqlite3_errmsg(PatientDatabase));
}
}
}
@catch (NSException * e) {
}
@finally
{
sqlite3_close(PatientDatabase);
sqlite3_finalize(dataRows);
PatientDatabase=nil;
}
}
所以任何人都可以建议为什么会出现这个问题。
答案 0 :(得分:1)
首先,考虑一下Mark的答案,如果您打开数据库一次并关闭它,您将获得更好的性能。
无论如何,这是对设计改进的建议。你的代码实际上有什么问题是finally块:
@finally
{
sqlite3_close(PatientDatabase); // will fail!
sqlite3_finalize(dataRows);
PatientDatabase=nil;
}
以下是sqlite3_close()文档中的相关行。
应用程序必须在尝试关闭对象之前完成所有预准备语句并关闭与sqlite3对象关联的所有BLOB句柄。如果在仍具有未完成的预准备语句或BLOB句柄的数据库连接上调用sqlite3_close(),则返回SQLITE_BUSY。
您需要在关闭数据库之前运行finalize。事实上,关闭调用失败,最终得到245个打开的数据库句柄。
因此,请颠倒两个陈述的顺序,并检查您的退货代码是否失败。
顺便说一下,NSAssert不是报告错误的合适方式。抛出异常或返回错误,或只记录它。 NSAssert旨在捕获编程错误。它甚至不会被编译到您的发布代码中。
答案 1 :(得分:0)
Sqlite有更好的表现"在翻译"在没有交易的插入。我特别是,大量使用事务处理过程,或者在某些时候随机出现故障而导致错误"无法打开数据库文件"
答案 2 :(得分:-1)
您在每次调用时打开数据库,打开它所需的资源较少,然后在关闭之前添加所有行。理论上你正在做的事情应该有效,但这不是我开始使用的方式。