Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.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 sqlite3\u准备\u v2/sqlite3\u执行_Ios_Objective C_Sqlite - Fatal编程技术网

Ios sqlite3\u准备\u v2/sqlite3\u执行

Ios sqlite3\u准备\u v2/sqlite3\u执行,ios,objective-c,sqlite,Ios,Objective C,Sqlite,关于sqlite3的几个问题: 1.何时需要使用第一种方法,何时需要使用第二种方法?他们之间有什么不同 sqlite3_prepare_v2(_contactDB, sql_stmt_getIdRecepteur, -1, &sqlStatement, NULL); 及 2.何时最适合使用“sqlite3\U exec”而不是“sqlite3\U prepare\U v2” 3.当需要使用第一个、第二个或第三个时: while(sqlite3_step(sqlStatement) ==

关于sqlite3的几个问题:

1.何时需要使用第一种方法,何时需要使用第二种方法?他们之间有什么不同

sqlite3_prepare_v2(_contactDB, sql_stmt_getIdRecepteur, -1, &sqlStatement, NULL);

2.何时最适合使用“sqlite3\U exec”而不是“sqlite3\U prepare\U v2”

3.当需要使用第一个、第二个或第三个时:

while(sqlite3_step(sqlStatement) == SQLITE_ROW){}
if(sqlite3_step(sqlStatement) == SQLITE_ROW){}
if(sqlite3_step(sqlStatement) == SQLITE_DONE){}

提前感谢您回答问题1,在大多数情况下,您需要验证结果是否等于SQLITE_OK,以确保您的命令成功运行。(SQLITE_OKisinttype**)。因此,优选第二种

对于问题2,函数sqlite3_exec用于运行任何不返回数据的命令,包括更新、插入和删除。从数据库中检索数据几乎不需要更多的工作。函数sqlite3\u prepare\u v2可用于选择(在
SQL
中)。通常,createtable通常使用第一个表

对于问题3中的表示循环,而中的表示条件。通常,如果从db中检索数据,则需要一个循环来遍历*返回数组**。例如,如果向db插入数据,可以使用SQLITE_DONE检查您的操作

顺便说一句,在大多数情况下,IOS中首选核心数据

  • 人们应该经常检查SQLite函数的返回值,以确保它成功,因此最好使用
    if
    语句。如果失败,则调用
    sqlite3\u errmsg()
    来检索错误的C字符串描述

  • 在以下任一情况下,可以使用
    sqlite3\u prepare\u v2
    (而不是
    sqlite3\u exec
    ):

    • 一个是返回数据,因此将调用
      sqlite3\u步骤
      ,然后调用一个或多个函数,对每行数据重复该过程;或

    • 一种是使用将值绑定到SQL中的
      占位符

    从上面可以推断,只有当(a)SQL字符串没有参数时,才会使用
    sqlite3\u exec
    ;(b)SQL不返回任何数据。sqlite3_exec更简单,但只应在这些特定情况下使用

    请注意:关于
    占位符的这一点非常重要:应避免手动构建SQL语句(例如,使用
    stringWithFormat
    或Swift字符串插值),尤其是在插入的值包括最终用户输入的情况下。例如,如果使用使用用户输入创建的
    INSERT
    UPDATE
    、或
    DELETE
    语句调用
    sqlite3\u exec
    (例如,将用户提供的某个值插入数据库),则可能会发现未转义的引号和转义符号所产生的问题,其中一个还面临SQL注入攻击

    例如,如果由于用户输入而提供了
    commentString
    ,这将是不可取的:

    NSString *sql = [NSString stringWithFormat:@"INSERT INTO COMMENTS (COMMENT) VALUES ('%@')", commentString];
    if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL) != SQLITE_OK) {
        NSLog(@"Insert failure: %s", sqlite3_errmsg(database));
    }
    
    相反,你应该:

    const char *sql = "INSERT INTO COMMENTS (COMMENT) VALUES (?)";
    if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) != SQLITE_OK) {
        NSLog(@"Prepare failure: %s", sqlite3_errmsg(database));
        return;
    }
    if (sqlite3_bind_text(statement, 1, [commentString UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK) {
        NSLog(@"Bind 1 failure: %s", sqlite3_errmsg(database));
        sqlite3_finalize(statement);
        return;
    }
    if (sqlite3_step(statement) != SQLITE_DONE) {
        NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    sqlite3_finalize(statement);
    
    注意,如果此正确的实现感觉工作量太大,则可以使用,这将简化为:

    if (![db executeUpdate:@"INSERT INTO COMMENTS (COMMENT) VALUES (?)", commentString]) {
        NSLog(@"Insert failure: %@", [db lastErrorMessage]);
    }
    
    这提供了
    sqlite3\u prepare\u v2
    方法的严格性,但提供了
    sqlite3\u exec
    接口的简单性

  • 检索多行数据时,将使用:

    while(sqlite3_step(sqlStatement) == SQLITE_ROW) { ... }
    
    或者,更好的做法是,如果您想进行正确的错误处理,您可以:

    int rc;
    while ((rc = sqlite3_step(sqlStatement)) == SQLITE_ROW) {
        // process row here
    }
    if (rc != SQLITE_DONE) {
         NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    
    检索单行数据时,可能会:

    if (sqlite3_step(sqlStatement) != SQLITE_ROW) {
        NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    
    if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
        NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    
    执行不会返回任何数据的SQL时,可能会:

    if (sqlite3_step(sqlStatement) != SQLITE_ROW) {
        NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    
    if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
        NSLog(@"Step failure: %s", sqlite3_errmsg(database));
    }
    

  • 当使用SQLite C接口时,您可以看到需要做一些工作才能正确地完成它。在这个名为的接口周围有一个很薄的Objective-C包装器,它不仅简化了与SQLite数据库的交互,而且更加健壮。

    我刚刚找到的对#2的最新答案是:使用
    sqlite3_exec
    (或者在循环中使用
    sqlite3_prepare_v2
    )当
    sql\u stmt\u getIdRecepteur
    实际包含多个sql语句时。从:

    这些例程只编译zSql中的第一条语句,因此*pzTail左指未编译的语句


    sqlite3\u exec
    包括一个内部循环,该循环多次调用
    sqlite3\u prepare\u v2
    ,直到编译整个输入字符串。如果您不使用
    sqlite3\u exec
    ,并且在一个字符串中有多个SQL语句,那么您需要检查
    pzTail
    sqlite3\u prepare\u v2
    返回的值,谢谢您的回答。当然,这应该在文档中!谢谢,顺便说一句,这里有一个小问题,虽然它没有详细说明什么时候方便函数,
    sqlite3\u exec
    ,是合适的,什么时候不合适。他们让你来推断。但它确实讨论了基本界面。很高兴知道。非常感谢在后台线程中运行所有这些时,我应该使用
    SQLITE\u TRANSIENT
    吗@罗伯/任何人。我在谷歌搜索时发现了。@LalKrishna-是的,我们应该使用
    SQLITE\u TRANSIENT
    。我已经相应地更新了这个。仅供参考,它与背景或前景无关:问题在于您是否希望SQLite使用复制语义。十有八九,您确实希望使用
    SQLITE\u TRANSIENT
    。正如文档中所说,“SQLITE_TRANSIENT值意味着内容在不久的将来可能会发生变化,SQLITE应该在返回之前制作自己的内容私有副本。”