SQLite

作者: 亡灵诅咒 | 来源:发表于2016-05-23 19:28 被阅读302次

    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)
        }
        ```
    
    

    相关文章

      网友评论

          本文标题:SQLite

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