Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios FMDB中未运行多个查询_Ios_Sqlite_Fmdb - Fatal编程技术网

Ios FMDB中未运行多个查询

Ios FMDB中未运行多个查询,ios,sqlite,fmdb,Ios,Sqlite,Fmdb,我正在使用FMDB在iPhone上创建一个SQLite数据库。我有一个初始的.sql,它的形式是 CREATE TABLE Abc ... ; CREATE TABLE Def ... ; 我通过将文件加载到NSString并运行它来加载它 NSString * str = // string from file initial.sql [db executeUpdate: str]; 这成功了,但后来我失败了: no such table: Def 很明显,第二个声明没有被调用。如何才

我正在使用FMDB在iPhone上创建一个SQLite数据库。我有一个初始的.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列表),该列表是以分号分隔的语句列表


所以,这一切都应该起作用。

我也被这个咬了;我花了整整一个上午的时间浏览FMDatabase并阅读SQLite3API文档来找到它。我仍然不能完全确定问题的根本原因,但根据,有必要调用,而不是使用sqlite3_prepare_v2准备语句,然后调用sqlite3_步骤

文档似乎没有表明这种行为会发生,因此我们感到困惑,我希望有更多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, NULL, &errorOutput);

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

    return true;
}
请注意,executeBatch缺少许多功能,这使得它不适合用于许多用途。具体来说,它不检查数据库是否被锁定,也不确保FMDatabase本身没有被锁定,它不支持语句缓存


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

FMDB v2.3现在为
sqlite3\u exec
提供了一个本机包装,名为:

Split Batch Statement
Add in .h file:
#import "FMSQLStatementSplitter.h"
#import "FMDatabaseQueue.h"

FMSQLStatementSplitter can split batch sql statement into several separated statements, then [FMDatabase executeUpdate:] or other methods can be used to execute each separated statement:

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:databasePath];
NSString *batchStatement = @"insert into ftest values ('hello;');"
                           @"insert into ftest values ('hi;');"
                           @"insert into ftest values ('not h!\\\\');"
                           @"insert into ftest values ('definitely not h!')";
NSArray *statements = [[FMSQLStatementSplitter sharedInstance] statementsFromBatchSqlStatement:batchStatement];
[queue inDatabase:^(FMDatabase *adb) {
    for (FMSplittedStatement *sqlittedStatement in statements)
    {
        [adb executeUpdate:sqlittedStatement.statementString];
    }
}];
它还有一个变量,它使用
sqlite3\u 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
}];

实际上,我最终只是确保我的批处理查询位于不同的行上,并按换行符进行拆分。然后我用BEGIN/COMMIT将其包围起来,使其成为一个事务。请看,这个“额外”已被替换为
sqlite3\u exec
的本机包装。只要调用
executeStatements
。我想大多数人都没有意识到,如果返回非零,它将停止。此外,我认为最好让你的街区决定你是否想停下来。正如我在这里所建议的,我想可能有人没有注意到,但是在Xcode中关于这个方法的快速帮助中有记录。我不知道你所说的“最好让你的区块决定你是否要停止”是什么意思,不过:
返回0
的目的就是告诉它继续。如果返回一个非零值,它将停止。
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
}];