美文网首页iOS进阶之路
iOS数据库的使用(二):sqlite3的常用方法及其使用

iOS数据库的使用(二):sqlite3的常用方法及其使用

作者: 康小曹 | 来源:发表于2019-05-16 20:08 被阅读0次

    sqlite对象

    每一个打开的数据库都使用一个不透明的sqlite对象来表示。其声明非常简单任性,只是使用typedef起了一个别名,如下:

    typedef struct sqlite3 sqlite3;
    

    sqlite3_initialize( )

    对应的有4个方法:

    int sqlite3_initialize(void);
    int sqlite3_shutdown(void);
    int sqlite3_os_init(void);// 可以忽略,initialize方法中已经根据不同的平台做了实现
    int sqlite3_os_end(void);// 可以忽略,initialize方法中已经根据不同的平台做了实现
    

    initialize方法和shutdown方法对应,os_init和os_end对应,在os系统中使用,其意义如下:

    • 构造方法和销毁方法一一对应且只能对一个对象调用一次,调用多次不会做额外操作且无伤害(harmless)
    • 构造方法需要在使用任何其他的sqlite api之前调用(sqlite3_config()方法需要在init之前调用),销毁方法需要在所有连接已经关闭且所有资源被释放的情况下调用
    • init方法线程安全,销毁方法线程不安全,销毁方法只能在一个线程中调用
    • 编译阶段可以设置自动调用初始化方法,但是官方建议手动调用初始化方法,因为以后的发布版本中会逐步使用非自动初始化的模式。许多方法在内部会自动调用初始化方法,比如open方法。如果是非自动初始化的模式,则需要自己手动调用。
    • 不能主动调用os_init和os_end,这两个函数已经被封装在了initialize方法中,会根据平台的不同进行不同的操作

    总结:这个方法一般被封装在了open当中,一般不需要主动调用(至少在iOS中使用sqlite3lib库时),是一个不需要重点关注的方法
    initialize方法官方文档

    sqlite3_open

    建立数据库连接的方法。open方法应该有三个:sqlite3_open、sqlite3_open16、sqlite3_open_v2。其中open方法内部调用的就是open_v2方法,只是配置的参数不一样,其区别如下:

    方法名 编码方式 第三个参数 第四个参数
    sqlite3_open UTF-8 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE NULL对象(默认的sqlite3_vfs对象)
    sqlite3_open16 UTF-16 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE NULL对象(默认的sqlite3_vfs对象)
    sqlite3_open_v2 UTF-8 可配置 可配置

    两个注意点:

    • open方法在建立连接时,无论成功还是失败,都会返回一个指针对象,唯一的例外是当内存不够分配给一个sqlite3对象时,open方法会返回一个NULL。所以,每次open最好判断是否成功,如果失败则主动close掉连接。

    • 对于open_v2第三个参数的配置要求为:必选+可选。必选为
      SQLITE_OPEN_READONLY、SQLITE_OPEN_READWRITE、SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE三个中的一个。可选项为下表中的任意配置,相关的官方文档

    sqlite3_open_v2

    sqlite3_open_v2方法需要重点关注,其声明如下:

    SQLITE_API int sqlite3_open_v2(
      const char *filename,   /* Database filename (UTF-8) */
      sqlite3 **ppDb,         /* OUT: SQLite db handle */
      int flags,              /* Flags */
      const char *zVfs        /* Name of VFS module to use */
    );
    

    参数的意义:
    第一个参数:fineName,就是要连接的数据库的文件名地址
    第二个参数:sqlite3对象,sqlite3中使用sqlite3对象来表示一个连接
    第三个参数:flags,打开数据库时配置的一些参数。下文会具体介绍。
    第四个参数:vfs

    open_v2和sqlite3_vfs.xOpen可配置的参数(这里的vfs是指第四个参数吗还是sqlite3_vfs.xOpen方法?):

    参数名 使用限制 意义
    SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ 只读
    SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ 可读可写
    SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ 没有则创建
    SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ ???
    SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ ???
    SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ ???
    SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ ???
    SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ ???
    SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ ???
    SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ ???
    SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ ???
    SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ ???
    SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ ???
    SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ ???
    SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ ???
    SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ 并发模式
    SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ 串行模式
    SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ 共享缓存模式
    SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ 私有缓存模式
    SQLITE_OPEN_WAL 0x00080000 /* VFS only */ ???

    sqlite3_prepare_v2

    sqlite3中的open方法的意义:sql的执行需要一个字节码程序。而prepare方法就是将sql语句生成一个二进制的程序等待被执行。另一个角度而言,prepare方法是生成一个 prepared statement对象,而这个对象就代表一个已经被编译成二进制格式的程序。
    prepare方法:prepare方法众多,其中sqlite3_prepare是历史遗留方法,不能使用,一般使用sqlite3_prepare_v2方法,其他方法可以参考官方文档
    参数的意义:第一第二个参数不做解释。第三个参数为负数时,从第一个字符开始读取到第一个终止符(也就是'\0'),所以为负数时就是指读取sql参数中的所有。为正数时指从第几个char字符开始读取,为0时不读取。pzTail指向被解析的字符串的末尾,一般为null,具体意义未知。
    ** ppStmt**:指向一个已经编译过的prepared statement,用于给将要执行的sql添加参数
    以插入的sql为例,具体使用如下:

    - (void)sqliteInsert {
        sqlite3 *sqlite;
        int result = sqlite3_open_v2(DATABASEPATH, &sqlite, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
        if(result != SQLITE_OK) {
            NSLog(@"error opening!: %d", result);
        } else {
            // 无论是否报错,database connection(也就是sqlite3对象)都会被分配内存,需要close来释放掉内存
            sqlite3_close(sqlite);
        }
        
        // 使用prepare插入
        NSString *insertSql = @"replace INTO ClientTable (name, no, signature) values ( ?, ?, ?);";
        
        sqlite3_stmt *statment;
        // prepared方法的作用是使用sql生成一个可执行的程序
        sqlite3_prepare_v2(sqlite, [insertSql UTF8String], -1, &statment, NULL);
        
        // 绑定句柄
        sqlite3_bind_text(statment, 1,[@"测试" UTF8String], -1, NULL);
        sqlite3_bind_text(statment, 2,[@"01" UTF8String], -1, NULL);
        sqlite3_bind_text(statment, 3,[@"测试签名" UTF8String], -1, NULL);
        
        // step是执行sql语句
        int errorNo = sqlite3_step(statment);
        if (errorNo != SQLITE_DONE) {
            NSLog(@"错误");
        }
        sqlite3_finalize(statment);
        sqlite3_close(sqlite);
    }
    

    sqlite3_bind()

    step

    finalize

    close

    sqlite3_reset()

    按照常规操作,bind后需要finalize对应的statement然后再次sqlite_prepare新的statement。但是sqlite_reset方法的效率是大于等于sqlite_prepare方法的,而sqlite_reset相当于将statement回滚到了最初的状态。所以使用reset可以显著地提高程序的性能表现

    step方法

    exec方法

    exec方法是对 sqlite3_prepare_v2()、sqlite3_step()、和 sqlite3_finalize()方法的封装。可以一步到位执行多个sql语句,插入语句的使用如下:
    注意点:
    1、要根据返回值判断是否执行成功,因为执行错误不一定会有errMsg(具体如何使用errMsg??)
    2、如果使用了errMsg,那么需要手动调用sqlite_free()方法来释放内存
    代码如下:

    vfs是什么?
    URI是什么?

    官方文档:2个对象和8个方法的概览 或者说是 sqlite中的核心接口和对象

    相关文章

      网友评论

        本文标题:iOS数据库的使用(二):sqlite3的常用方法及其使用

        本文链接:https://www.haomeiwen.com/subject/eejvaqtx.html