SQLite

Sqlite

简介
  • iOS数据存数的方式
  • plist(NSArray/NSDictionary) 特点:自能存储系统自带的数据类型,自定义对象无法存储
  • preference(偏好设置)特点:本质就是一个Plist文件,也只能存储系统自带的数据类型,自定义对象无法存储
  • NSCoding 特点可以存储自定义的数据类型,但是是一次性的全数据操作
  • SQLite3 特点:存储一些大批量的数据,排序,统计操作
  • Core Data 特点:对SQLite3的封装,本质上还是SQL语句执行,
  • 钥匙串
SQLite
  • SQLite是一款轻型的嵌入式数据库,它占用的资源非常低,在嵌入式设备中,可能只需要几百K的内存就够了,它处理的速度比Mysql这款注明的数据库还快
Swift中使用SQLite
  • 创建项目,导入系统的框架sqlite3.tgb
  • 需要创建桥接文件,导入头文件sqlite3.h
  • 代码实现打开数据库
    //sqlite数据库文件的扩展名称没有一个标准,一般流行都是以sqlite,db,db3命名
     var db :COpaquePointer = nil
     func openDataBase(){
        let filename = "/Users/dingkan/Desktop" + "/demo.sqlite"
        //sqlite3_open方法用来创建打开一个数据库
        //参数一:sqlite数据库的路径
        //参数二: 一个指向SQLite3的数据的结构指针,到时候操作数据库都需要用到这个对象
        //作用:通过一个路径来创建数据库,如果路径处存在数据域,那么久打开该数据库,如果不存在就创建一个数据库
        if sqlite3_open(filename, &db) != SQLITE_OK {
            print("数据库创建失败")
        }else{
            print("数据库创建成功")
        }
    }
    
DDL语句
  • 1.创建一个数据库表
    func creatTable(){ 
        //创建sqlite语句
         let sql = "CREATE TABLE if not exists t_Student(id integer PRIMARY KEY AUTOINCREMENT,name text not NULL, age integer default 18, source integer)"
        //参数一: 一个打开的数据库
        //参数二: sql语句
        //参数三:回调结果,执行完毕后回调的函数,如果不需要可以传nil
        //参数4:参数三的第一个参数,可以通过这个参数传值给回调的函数,如果不需要就传nil
        //参数5:错误信息
        if sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK {
            print("列表创建成功")
        }else{
            print("列表创建失败")
        }
    
  • 2.删除数据库表
        //删除表格
    func dropTable(){
        let sql = "drop table if exists t_Student"
        if exec(sql){
            print("删除成功")
        }else{
            print("删除失败")
        }
    }
    
  • 3.修改数据库表
       func alterTable(){
        let sql = "alter table t_Student add column name text"
        if exec(sql){
            print("添加成功")
        }else{
            print("添加失败")
        }
    }
    //抽取
        func exec(sql: String) ->Bool{
        return sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK
    }
    
DML语句
  • 1.插入数据
    -sqlit语句格式:insert into 表名(字段1,字段2...) values(字段1的值,字段2的值...);
    -利用代码来插入数据

        func insert()->Bool{
        let sql = "insert into t_Student(name, age, source) values('\(name)' , \(age),\(source))"
        return Tool.shareInstance.exec(sql)
    }
    
  • 2.更新数据

    • sqlite语句格式:update 表名 set 字段1 = 字段1的值, 字段2 = 字段2的值...;
    • 利用代码来实现更新数据
        class func update(stu:DKStudent)->Bool{
        let sql = "update t_Student set name='\(stu.name)',age = \(stu.age), source = \(stu.source)"
        return Tool.shareInstance.exec(sql)
    }
    
  • 3.删除数据

    • sqlite语句格式: delete from 表名 Where 字段1 = 字段1的值...;
    • 利用代码来实现删除数据
        func delete()->Bool{
        let sql = "delete from t_Student where name = '\(name)'"
        return Tool.shareInstance.exec(sql)
    }
    
  • Insert绑定参数

  • 准备语句(prepared tatement)对象,准备语句对象,代表了一个简单的SQL语句对象的实例,这个对象通常被称作准备语句获取编译好的SQL语句

  • 操作过程

    • 1.创建准备语句对象,如果执行成功,则返回SQLITE_OK,否则返回一个错误码

//1.固定写法
let sql = "insert into t_Student(name, age, source) values(?, ?, ?)"
//2.创建准备语句
let db = Tool.shareInstance.db
参数一: 数据库
参数二: sql语句
参数三: 代表从sql字符串中取出的长度, -1代表自动计算
参数四: 代表准备语句地址
参数五: 按照参数三从参数二中取出字符串剩下的字符串
//创建一个空的准备语句,获取返回的结果
var stmt : COpaquePointer = nil
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK{
print("编译失败")
return
}


    - 2.绑定参数
    ```
//  绑定参数
//参数一: 准备语句
//参数二: 绑定的参数索引(从1开始)
//参数三: 绑定的参数的内容
//参数四: 绑定参数的长度 -1代表自动计算
//参数五: 参数的处理方式
// #define SQLITE_STATIC      会对字符串做一个copy,SQLite选择合适的机会释放
 //#define SQLITE_TRANSIENT    会当做全局静态变量,不会对字符串做任何处理,如果字符串被释放,保存到数据库的内容可能不正确
 //swift中没有宏的概念,所以需要替换
let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)
sqlite3_bind_text(stmt, 1,"aa", -1, SQLITE_TRANSIENT)
sqlite3_bind_int(stmt, 2, 13)
sqlite3_bind_double(stmt, 3, 80.0)
    ```
    
    - 3.执行sql
    ```
    //对于DML语句,如果执行成功,则返回SQLITE_DONE,
    //对于DQL语句,通过多次执行获取结果集,继续执行的条件是SQLITE_ROW
    if sqlite3_step(stmt) != SQLITE_DONE{
        print("执行失败")
        return
        }
    ```
    - 4.重置语句
    ```
    sqlite3_reset(stmt)//使用sqlite3_reset()重置这个语句,让后回到上一步,绑定参数,这个过程可能做0次,也可能左多次
    ```
    - 5.销毁对象,防止内存泄露
    ```
    sqlite3_finalize()
    ```
    
#####Transaction事务
- 事务是并发控制的单位,是用户定义的一个操作序列,这个操作要么做,要么都不做,是一个不可分割的工作单位,通过事务,可以将逻辑相关的一些操作绑定在一起,保证数据的完整性
-使用事务来优化
- 大批量数据插入的优化
- 第一层优化: 使用`准备语句`
- 第二层优化: 无论是sqlite3_exec,还是sqlite3_step,都会在内容自动`开启事务`,自动`提交事务`,一旦自动开启,自动提交,就会非常的耗时,
- 解决方案: 只要我们手动开启,和手动提交,那么系统就不会来自动执行,

######DQL语句
- 代码实现DQL语句的方式
- 方式一: 利用sqlite3_exec来实现,作用: 可以通过回调来获取结果,步骤相对简单,结果数据类型没有特定类型(id)
    ```
        func queryALl(){
        //方式一: 通过sqlite_exec来查询
        //sql语句
        let sql = "select * from t_Student"
        let db = Tool.shareInstance.db
        //参数一:可以打开的数据库
        //参数二:需要执行的SQL语句
        //参数三 查询结果回调
            //参数1: 参数4的值
            //参数2: 列的个数
            //参数3: 结果值的数组
            //参数4: 所有列的名称数组
            //返回值为0 表示继续查询,返回值非0 表示终止查询
        //参数四:回调函数的第一个参数
        //参数五:错误信息
        sqlite3_exec(db, sql, { (firsPara, columnCount, values, columnNames) -> Int32 in
        //将UnsafeMutablePointer<Int8>转换成int类型
            let count = Int(columnCount)
            for i in 0..<count{
            //取出每一列的名称和对应的值
                let valueC = values[i]
                let value = String(CString: valueC, encoding: NSUTF8StringEncoding)
                //需要转换成字符串类型
                let nameC = columnNames[i]
                let name = String(CString: nameC, encoding: NSUTF8StringEncoding)
                print(value, name)
            }
            return 1//0表示继续查询,非0表示终止插叙
            }, nil, nil)
    }
    ```
    
- 方式二:通过准备语句来实现,可处理不同特定类型
    ```
       class func queryAllStmt() {  
        let sql = "select * from t_Student"
        // 1. 创建一个准备语句
        let db = SQLiteTool.shareInstance.db
        var stmt: COpaquePointer = nil
        if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
            print("预处理失败")
            return
        }
        // 2. 绑定参数(可以省略)
        // 3. 执行,如果下一行没有内容就不会执行
        while sqlite3_step(stmt) == SQLITE_ROW {
            // 1. 确定有多少列
            let count = sqlite3_column_count(stmt)
            // 2. 遍历所有的列
            for i in 0..<count {
                // 3. 取出列名, 列对应的值
                let columnName = sqlite3_column_name(stmt, i)
                let columnNameStr = String(CString: columnName, encoding: NSUTF8StringEncoding)
                print(columnNameStr)
                // 应该根据列对应的类型, 使用不同的函数, 来取出不同的值
                let type = sqlite3_column_type(stmt, i)
                // 2. 根据不同的类型, 使用不同的函数, 取出不同的值!
                if type == SQLITE_INTEGER {
                    let value = sqlite3_column_int(stmt, i)
                    print(value)
                }
                if type == SQLITE_FLOAT {
                    let value = sqlite3_column_double(stmt, i)
                    print(value)
                }
                if type == SQLITE3_TEXT {
                    let value = UnsafePointer<CChar>(sqlite3_column_text(stmt, i)) 
                    let valueStr = String(CString: value, encoding: NSUTF8StringEncoding)
                    print(valueStr)
                }
            }
        }
        // 4. 重置(可以省略)
        // 5. 释放资源
        sqlite3_finalize(stmt)
    }
    ```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容