我正在使用FMDB在iPhone上创建一个sqlite数据库.我有一个形式的initial.sql
CREATE TABLE Abc ... ; CREATE TABLE Def ... ;
我通过将文件加载到NSString并运行它来加载它
NSString * str = // string from file initial.sql [db executeUpdate: str];
这成功但后来我失败了:
no such table: Def
根据sqlite文档:
“例程sqlite3_prepare_v2(),sqlite3_prepare(),sqlite3_prepare16(),sqlite3_prepare16_v2(),sqlite3_exec()和sqlite3_get_table()接受一个sql语句列表(sql-stmt-list),它是一个以分号分隔的语句列表.”
所以,这应该都有效.
解决方法
我也被这个人咬了;我花了整整一个上午踩过FMDatabase并阅读sqlite3 API文档来找到它.我仍然不完全确定问题的根本原因,但根据
this bug in PHP,有必要调用
sqlite3_exec,而不是使用sqlite3_prepare_v2准备语句,然后调用sqlite3_step.
文档似乎没有暗示这种行为会发生,因此我们的困惑,我希望有更多经验的sqlite提出一些假设.
我通过开发一个执行一批查询的方法解决了这个问题.请在下面找到代码.如果您愿意,可以将其重写为一个类别,而不是仅将其添加到您的调用FMDatabase.h中.
将其添加到FMDatabase.h中的FMDatabase接口:
- (BOOL)executeBatch:(NSString*)sql error:(NSError**)error;
将其添加到FMDatabase.m中的FMDatabase实现:
- (BOOL)executeBatch:(NSString *)sql error:(NSError**)error { char* errorOutput; int responseCode = sqlite3_exec(db,[sql UTF8String],NULL,&errorOutput); if (errorOutput != nil) { *error = [NSError errorWithDomain:[NSString stringWithUTF8String:errorOutput] code:responseCode userInfo:nil]; return false; } return true; }
请注意,executeBatch中缺少许多功能,这使得它不适用于很多用途.具体来说,它不检查数据库是否被锁定,它不确保FMDatabase本身没有被锁定,它不支持语句缓存.
如果您需要,以上是自己编码的好起点.快乐的黑客!