数据库(SQLite)
01-多表查询
- 格式:select 字段1,字段2,... from 表名1,表名2;
- 别名:select 别名1.字段1 as 字段别名1,别名2.字段2 as 字段别名2,... from 表名1 as 别名1,表名2 as 别名2;
- 可以给表或字段单独起别名,as可省略
- 表连接查询:select 字段1,字段2,... from 表名1,表名2 where 表名1.id = 表名2.id;
- 外键:
- 如果表A的主关键字是表B中的字段,则该字段成为表B的外键
- 保持数据的一致性,完整性,主要目的是控制存储在外键表中的数据
- 使两张表形成关联,外键只能引用外表中列的值或使用空值
02-代码实现DDL语句
- 创建swift项目
- 导入系统框架sqlite3.tdb(sqlite3.dylib)
- 在Build Setting中搜索bridging,找到Objective-C Bridging Header,设置一个.h文件路径为桥接文件
- 打开桥接文件,导入头文件"sqlite3.h"
- 代码实现
- 打开数据库
- 获取沙盒路径,然后创建数据库的存储路径
- SQlite3数据库文件的扩展名没有一个标准定义,比较流行的选择是.sqlite3、.db、.db3
- 使用打开的数据库,执行DDL语句,创建一个数据库表
- 使用打开的数据库,执行DDL语句,删除一个数据库表
- 将数据库操作封装成一个工具类
03-代码实现DML语句
1.insert绑定参数
- 准备语句(prepared statement)对象
- 准备语句对象代表一个简单SQL语句对象的实例,这个对象通常被称为"准备语句"或者"编译好的SQL语句"或者就直接称为"语句"
- 操作历程:
- 使用sqlite3_prepare_v2或者相关的函数创建这个对象,如果执行成功,则返回SQLITE_OK,否则返回一个错误码
- 使用sqlite3_bind_*()给宿主参数绑定值
- 通过调用sqlite3_step()一次或多次来执行这个sql
- 对于DML语句,如果执行成功,返回SQLITE_DONE
- 对于DQL语句,通过多次执行获取结果集,继续执行的条件是返回值SQLITE_ROW
- 使用sqlite3_reset()重置这个语句,然后回到第2步,这个过程做0次或多次
- 使用sqlite3_finalize()销毁这个对象,防止内存泄漏
2.insert插入数据优化
- sqlite_exec直接执行和未拆解"准备语句"平均执行时间差不多
- sqlite_exec函数是对"准备语句"的封装
- (预处理语句->绑定参数->执行语句->重置语句->释放语句)
- 拆解后的"准备语句"执行,效率明显高了一些,主要原因是真准遵循了"准备语句"的操作流程
- 虽然按步骤使用"准备语句",但是执行效率依然不如意
- 原因分析:每当SQL调用执行方法执行了一个语句,都会开启一个叫事务的东西,执行完毕后再提交事务,也就是说,如果执行了10000次SQL语句,就打开和提交了10000次事务,所以造成耗时严重.
- 解决方案:只要在执行多个SQL语句之前,手动开启事务,在执行完毕之后,手动提交事务,这样再调用SQL方法执行语句时,就不会再自动开启和提交事务.
- 优化后的结果:插入10000条数据,大概耗时0.07秒
- 得出结论:
- 如果插入大量数据,请务必手动开启/提交事务
- 根据不同情况,选择使用sqlite3_exec或者"准备语句",如果操作单条语句,使用前者,如果大批量操作,选择后者
04-代码实现事务
- 概念:
- 事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.
- 这些操作要么都做,要么都不做,是一个不可分割的工作单位.
- 通过事务,可以将逻辑相关的一组操作绑定在一起,保持数据的完整性.
- 事务通常是以begin transaction开始,以commit transaction或者rollback transaction结束
- commit表示提交,即提交事务的所有操作.具体的说就是将事务中所有对数据库的更新写回磁盘上的物理数据库中去,事务正常结束.
- rollback表示回滚,即在事务运行得过程中发生了某些故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始的状态.
05-代码实现DQL语句
1.使用sqlite3_exec
- 作用:可以通过回调来获取结果,步骤相对来说简单,结果数据类型没有特定类型(id)
- 参数说明
- 参数1:一个打开的数据库
- 参数2:需要执行的SQL语句
- 参数3:查询结果回调(执行0次或多次)
- 参数1:参数4的值
- 参数2:列的个数
- 参数3:结果值的数组
- 参数4:所有列的名称数组
- 返回值:0代表继续执行直到结束,1代表执行1次
- 参数4:回调函数的第一个值
- 参数5:错误信息
2.使用"准备语句"
- 作用:可以处理不同特定类型,步骤相对来说复杂
- 步骤:
- 通过预处理函数,获取"准备语句" sqlite3_prepare
- 不断执行"准备语句",直到无结果集 while sqlite3_step(stmt) == SQLITE_ROW
- 获取列的类型 sqlite3_column_type
- 根据每列的类型取出不同的值
- sqlite3_column_int64 SQLITE_INTEGER
- sqlite3_column_double SQLITE_FLOAT
- sqlite3_column_text SQLITE_TEXT
- 需要转换下字符串
- let cText = UnsafePointer(sqlite3_column_text(stmt,col))
- let text = String(CString:cText,encoding:NSUTF8StringEncoding)
- NSNull() SQLITE_NULL
- 释放资源 sqlite3_finalize
06-FMDB基本使用
1.什么是FMDB
- FMDB是iOS平台的SQLite框架
- FMDB以OC的方式封装了SQLite的C语言API
2.FMDB有什么优势
- 使用起来更加面向对象,省去了很多麻烦,冗余的C语言代码
- 提供了多线程安全的数据库操作方法,有效地防止数据混乱
3.安装方式
- Cocoapods:"use_framework!",使用dynamic frameworks的方式集成
- 手动集成(swift):
- 导入FMDB文件
- 导入系统依赖库sqlite3.0.tbd
- 建立桥接文件,并导入需要的头文件
4.核心类
- FMDatabase
- 一个FMDatabase对象就代表一个独立的SQLite数据库
- 用来执行SQL语句
- FMResultSet
- FMDatabaseQueue
5.使用步骤
- 打开数据库
- 通过指定SQLite数据库文件路径来创建FMDatabase对象
- 文件路径有3种情况:
- 具体文件路径(如果不存在会自动创建)
- 空字符串@""(会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除)
- nil(会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁)
- FMDatabase *db = [FMDatabase databaseWithPath:path];
- if([db open])
- 执行更新
- 在FMDB中,除查询以外的所有操作,都称为"更新"
- create/drop/insert/update/delete等
- 使用executeUpdate方法执行更新
- 执行查询
- 关闭数据库:database.close();
07-FMDatabaseQueue
- FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题
- 为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类
- FMDatabaseQueue的创建
- FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
- 简单使用
- [queue inDatabase:^(FMDatabase *db){在里面通过db执行SQL语句获取结果,对数据进行处理}];
- 使用事务
- [queue inTransaction:^(FMDatabase *db,BOOL *rollback){在里面通过db执行SQL语句获取结果,对数据进行处理}];
posted @
2016-12-22 11:32
喳喳的夏天
阅读(
308)
评论()
编辑
收藏
举报