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中的核心接口和对象
网友评论