多个查询未在FMDB中运行

Geo*_*rge 8 sqlite fmdb ios

我正在使用FMDB在iPhone上创建一个SQLite数据库.我有一个形式的initial.sql

CREATE TABLE Abc ... ;
CREATE TABLE Def ... ;
Run Code Online (Sandbox Code Playgroud)

我通过将文件加载到NSString并运行它来加载它

NSString * str = // string from file initial.sql

[db executeUpdate: str];
Run Code Online (Sandbox Code Playgroud)

这成功但后来我失败了:

no such table: Def
Run Code Online (Sandbox Code Playgroud)

很明显,第二个声明没有被调用.我该怎么做才能调用所有查询?

根据SQLite文档:"例程sqlite3_prepare_v2(),sqlite3_prepare(),sqlite3_prepare16(),sqlite3_prepare16_v2(),sqlite3_exec()和sqlite3_get_table()接受一个SQL语句列表(sql-stmt-list),这是一个分号 - 分开的陈述清单."

所以,这一切都应该有效.

Ste*_*uts 8

我也被这个人咬了; 我花了一整个上午踩过FMDatabase并阅读sqlite3 API文档来找到它.我仍然不完全确定问题的根本原因,但根据PHP中的这个错误,有必要调用sqlite3_exec而不是使用sqlite3_prepare_v2准备语句然后调用sqlite3_step.

文档似乎没有暗示这种行为会发生,因此我们的困惑,我希望有更多sqlite经验的人能够提出一些假设.

我通过开发一个执行一批查询的方法解决了这个问题.请在下面找到代码.如果您愿意,可以将其重写为一个类别,而不是仅将其添加到您的调用FMDatabase.h中.

将其添加到FMDatabase.h中的FMDatabase接口:

- (BOOL)executeBatch:(NSString*)sql error:(NSError**)error;
Run Code Online (Sandbox Code Playgroud)

将其添加到FMDatabase.m中的FMDatabase实现:

- (BOOL)executeBatch:(NSString *)sql error:(NSError**)error
{
    char* errorOutput;
    int responseCode = sqlite3_exec(db, [sql UTF8String], NULL, NULL, &errorOutput);

    if (errorOutput != nil)
    {
        *error = [NSError errorWithDomain:[NSString stringWithUTF8String:errorOutput]
                                     code:responseCode 
                                 userInfo:nil];
        return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

请注意,executeBatch缺少许多功能,这使得它不适用于很多用途.特别是,它不检查,以查看是否数据库已被锁定,它不确保FMDatabase本身没有被锁定,它不支持语句缓存.

如果您需要,以上是自己编写代码的好起点.快乐的黑客!


Rob*_*Rob 8

FMDB v2.3现在有一个sqlite3_exec名为的本机包装器executeStatements:

BOOL success;

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
                 "create table bulktest2 (id integer primary key autoincrement, y text);"
                 "create table bulktest3 (id integer primary key autoincrement, z text);"
                 "insert into bulktest1 (x) values ('XXX');"
                 "insert into bulktest2 (y) values ('YYY');"
                 "insert into bulktest3 (z) values ('ZZZ');";

success = [db executeStatements:sql];
Run Code Online (Sandbox Code Playgroud)

它还有一个使用sqlite3_exec回调的变体,实现为块:

sql = @"select count(*) as count from bulktest1;"
       "select count(*) as count from bulktest2;"
       "select count(*) as count from bulktest3;";

success = [db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) {
    NSInteger count = [dictionary[@"count"] integerValue];
    NSLog(@"Count = %d", count);
    return 0;   // if you return 0, it continues execution; return non-zero, it stops execution
}];
Run Code Online (Sandbox Code Playgroud)