说说SQLite在移动开发的那些事儿

说说SQLite在移动开发的那些事儿,第1张

概述SQLite 简介 http://www.sqlite.org/ 是一款轻型的数据库 设计目标是嵌入式的 占用资源少 处理速度快 当前版本 3.8.10.2,MAC 内置已经安装了 SQLite 什么是 SQLite? SQLite 是一个进程内的库,本质上就是一个文件,是一个 SQL 数据库引擎,具有: 自给自足 不需要任何外部的依赖 无服务器 不需要一个单独的服务器进程或 *** 作的系统 零配置 不 sqlite 简介

http://www.sqlite.org/

是一款轻型的数据库 设计目标是嵌入式的 占用资源少 处理速度快 当前版本 3.8.10.2,MAC 内置已经安装了 sqlite 什么是 sqlite?

sqlite是一个进程内的库,本质上就是一个文件,是一个 sql 数据库引擎,具有:

自给自足 不需要任何外部的依赖 无服务器 不需要一个单独的服务器进程或 *** 作的系统 零配置 不需要安装或管理 一个完整的 sqlite 数据库就是一个单一的磁盘文件 轻量级 完全配置时小于 400K,省略可选功能配置时小于250K 事务性支持

而服务端使用的数据库,如:Orcal,sql Server,MysqL...则需要独立的服务器,安装,配置,维护……

关系型数据库的特点 一个字段(Col)存储一个值,类似于对象的一个属性 一行(ROW)存储一条记录,类似于一个对象 一个表(table)存储一系列数据,类似于对象数组 多个之间存在一定关系,类似于对象之间的关系,例如:一条微博数据中包含用户记录 术语 字段(FIEld/Col):一个字段存储一个值,可以存储INTEGER,REAL,TEXT,BLOB,NulL五种类型的数据 sqlite 在存储时,本质上并不区分准确的数据类型 主键:Primary Key唯一标示一条记录的字段,具有以下特点: 名字:xxx_ID 类型:Integer 自动增长 准确数值由数据库决定,程序员不用关心 外键:Foreign Key,对应其他关系表的标示,利用外键可以和另外一个建立起"关系" 方便数据维护 节约存储空间 开发数据库的步骤 建立数据库 -> 有存储数据的文件 创建数据表 -> 每一张数据表存储一类数据 利用sql 命令实现增/删/查/改,并在 UI 中显示 移动应用中使用数据库的好处 将网络数据存储在本地,不用每次都加载,减少用户网络流量开销 对本地数据进行查询 sqlite 命令 DDL - 数据定义语言
命令 描述
CREATE 创建一个新的表,一个表的视图,或者数据库中的其他对象
ALTER 修改数据库中的某个已有的数据库对象,比如一个表
DROP 删除整个表,或者表的视图,或者数据库中的其他对象
不需要记忆,可以直接从客户端软件复制/粘贴 DML - 数据 *** 作语言
命令 描述
INSERT 新增
UPDATE 修改
DELETE 删除
需要掌握,语法固定,简单 DQL - 数据查询语言
命令 描述
SELECT 查询
需要掌握一些简单的查询指令 常用 sql 创建表
/* 创建数据表 CREATE table '表名' ( '字段名' 类型(INTEGER,REAL,TEXT,BLOB) NOT NulL 不允许为空 PRIMARY KEY 主键 autoINCREMENT 自增长,'字段名2' 类型,... ) 注意:在开发中,如果是从 Navicat 粘贴的 sql,需要自己添加一个指令 IF NOT EXISTS 加在表名前,如果数据表已经存在,就什么也不做 */CREATE table IF NOT EXISTS "T_Person" ( "ID" INTEGER NOT NulL PRIMARY KEY autoINCREMENT,"name" TEXT,"age" INTEGER,"heigth" REAL ) /* 简单约束 */ CREATE table IF NOT EXISTS t_student ( ID INTEGER PRIMARY KEY autoINCREMENT,name TEXT,age INTEGER );CREATE table IF NOT EXISTS t_student ( ID INTEGER PRIMARY KEY autoINCREMENT,name TEXT UNIQUE,age INTEGER );/* 添加主键 */CREATE table IF NOT EXISTS t_student ( ID INTEGER PRIMARY KEY autoINCREMENT,age INTEGER,score REAL );/* 添加主键 */CREATE table IF NOT EXISTS t_student ( ID INTEGER,score REAL,PRIMARY KEY(ID) );


插入
INSERT INTO t_student (age,score,name) VALUES ('28',100,'zhangsan'); INSERT INTO t_student (name,age) VALUES ('lisi','28');INSERT INTO t_student (score) VALUES (100);


修改
UPDATE t_student SET name = 'MM' WHERE age = 10;UPDATE t_student SET name = 'WW' WHERE age is 7;UPDATE t_student SET name = 'XXOO' WHERE age < 20;UPDATE t_student SET name = 'NNMM' WHERE age < 50 and score > 10;/*更新记录的name*/UPDATE t_student SET name = 'zhangsan';


删除
DELETE FROM t_student;DELETE FROM t_student WHERE age < 50;


查询
/* 分页 */SELECT * FROM t_student ORDER BY ID ASC liMIT 30,10;/* 排序 */SELECT * FROM t_student WHERE score > 50 ORDER BY age DESC;SELECT * FROM t_student WHERE score < 50 ORDER BY age ASC,score DESC;/* 计量 */SELECT COUNT(*) FROM t_student WHERE age > 50;/* 别名 */SELECT name as myname,age as myAge,score as myscore FROM t_student;SELECT name myname,age myAge,score myscore FROM t_student;SELECT s.name myname,s.age myAge,s.score myscore FROM t_student s WHERE s.age > 50;/* 查询 */SELECT name,age,score FROM t_student;SELECT * FROM t_student;


删除表
/*删除表*/DROP table IF EXISTS t_student;





sqlite核心对象 核心对象 & 核心接口 核心对象

database_connection

sqlite3_open函数创建并返回 在使用其他sqlite接口函数之前,必须先获得database_connnection对象

prepared_statement

可以简单的将它视为编译后的SQL语句 核心接口

sqlite3_open

可以打开已经存在的数据库文件 如果数据库不存在,可以创建新的数据库文件 返回的database_connection对象是其他sqlite APIs的句柄参数 可以在多个线程之间共享该对象指针

sqlite3_prepare

sql文本转换为prepared_statement对象 不会执行指定的sql语句 只是将sql文本初始化为执行的状态

sqlite3_step

执行一次sqlite3_prepare函数返回的prepared_statement对象 执行完该函数后,prepared_statement对象的内部指针将指向其返回结果集的第一行 如果要获得后续的数据行,则需要不断地调用该函数,直到所有的数据行遍历完毕 对于INSERTUPDATEDELETEDML语句,执行一次即可完成

sqlite3_column

用于获取当前行指定列的数据 以下函数分别对应不同的数据类型 sqlite3_column_blob sqlite3_column_bytes sqlite3_column_bytes16 sqlite3_column_double sqlite3_column_int sqlite3_column_int64 sqlite3_column_text sqlite3_column_text16 sqlite3_column_type sqlite3_column_value sqlite3_column_count 用于获取当前结果集中的字段数量

sqlite3_finalize

销毁prepared_statement对象,否则会造成内存泄露

sqlite3_close

关闭之前打开的database_connection对象 所有和该对象相关的prepared_statements对象都必须在此之前被销毁 Swift 中使用 sqlite 准备工作 添加libsqlite3.tbd 创建sqlite-BrIDge.h sqlite3框架是一套C语言的框架,因此需要添加桥接文件 选择项目-TARGETS-Build Settings,搜索BrIDgObjective-C BrIDging header中输入项目名/sqlite-BrIDge.h 如果之前设置过桥接文件,可以直接使用


编译测试

sqliteManager

与网络接口的独立类似,数据库的底层 *** 作,也应该有一个独立的对象单独负责

sqliteManager单例 新建sqliteManager.swift,并且实现以下代码:
/// sqlite 管理器class sqliteManager {    /// 单例    static let sharedManager = sqliteManager()}
数据库访问 *** 作需求 建立数据库 -> 有存储数据的文件 创建数据表 -> 每一张数据表存储一类数据 利用sql 命令实现增/删/查/改,并在 UI 中显示 建立&打开数据库
/// 数据库句柄private var db: copaquePointer = nil/// 打开数据库////// - parameter dbname: 数据库文件名func openDB(dbname: String) {    let path = (NSSearchPathForDirectorIEsInDomains(NSSearchPathDirectory.documentDirectory,NSSearchPathDomainMask.UserDomainMask,true).last! as Nsstring).stringByAppendingPathComponent(dbname)    print(path)    if sqlite3_open(path,&db) != sqlITE_OK {        print("打开数据库失败")        return    }    print("打开数据库成功")}
代码小结 建立数据库需要给定完整的数据库路径 sqlite3_open函数会打开数据库,如果数据库不存在,会新建一个空的数据库,并且返回数据库指针(句柄) 后续的所有数据库 *** 作,都基于此数据库句柄进行 打开数据库 在AppDelegate中添加以下代码
func application(application: UIApplication,dIDFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {    sqliteManager.sharedManager.openDB("my.db")    return true}
代码小结 sqlite数据库是直接保存在沙盒中的一个文件,只有当前应用程序可以使用 在移动端开发时,数据库通常是以持久式连接方式使用的 所谓持久式连接指的是只做一次打开数据库的 *** 作,永远不做关闭数据库的 *** 作,从而可以提高数据库的访问效率 创建数据表 如果是第一次运行,打开数据库之后,只能得到一个空的数据,没有任何的数据表 为了让数据库正常使用,在第一次打开数据库后,需要执行创表 *** 作

注意:创表 *** 作本质上是通过执行sql语句实现的

执行sql语句函数
/// 执行 sql////// - parameter sql: sql////// - returns: 是否成功func execsql(sql: String) -> Bool {    /** 参数 1. 数据库句柄 2. 要执行的 sql 语句 3. 执行完成后的回调,通常为 nil 4. 回调函数第一个参数的地址,通常为 nil 5. 错误信息地址,通常为 nil */    return sqlite3_exec(db,sql,nil,nil) == sqlITE_OK}
创建数据表
/// 创建数据表////// - returns: 是否成功private func createtable() -> Bool {    let sql = "CREATE table IF NOT EXISTS T_Person \n" +        "('ID' INTEGER NOT NulL PRIMARY KEY autoINCREMENT,\n" +        "'name' TEXT,\n" +        "'age' INTEGER);"    print(sql)    return execsql(sql)}
调整openDB函数
if createtable() {    print("创表成功")} else {    print("创表失败")    db = nil}
代码小结 创表sql可以从Navicat中粘贴,然后做一些处理 将"替换成' 在每一行后面增加一个\n防止字符串拼接因为缺少空格造成sql语句错误 在表名前添加IF NOT EXISTS防止因为数据表存在出现错误 数据模型 建立Person模型
class Person: NSObject {    /// ID    var ID: Int = 0    /// 姓名    var name: String?    /// 年龄    var age: Int = 0    /// 使用字典创建 Person 对象    init(dict: [String: AnyObject]) {        super.init()        setValuesForKeysWithDictionary(dict)    }}
新增数据
/// 将当前对象插入到数据库////// - returns: 是否成功func insertPerson() -> Bool {    assert(name != nil,"姓名不能为空")    let sql = "INSERT INTO T_Person (name,age) VALUES ('\(name!)',\(age));"    return sqliteManager.sharedManager.execsql(sql)}
在视图控制器添加如下代码,测试新增数据
/// 测试插入数据func demoInsert() {    print(Person(dict: ["name": "zhangsan","age": 18]).insertPerson())}
更新记录
/// 更新当前对象在数据库中的记录////// - returns: 是否成功func updatePerson() -> Bool {    assert(name != nil,"姓名不能为空")    assert(ID > 0,"ID 不正确")    let sql = "UPDATE T_Person SET name = '\(name!)',age = \(age) WHERE ID = \(ID);"    return sqliteManager.sharedManager.execsql(sql)}
在视图控制器添加如下代码,测试更新数据
/// 测试更新记录func demoUpdate() {    print(Person(dict: ["ID": 1,"name": "lisi","age": 20]).updatePerson())}
删除数据
/// 删除当前对象在数据库中的记录////// - returns: 是否成功func deletePerson() -> Bool {    assert(ID > 0,"ID 不正确")    let sql = "DELETE FROM T_Person WHERE ID = \(ID);"    return sqliteManager.sharedManager.execsql(sql)}
在视图控制器添加如下代码,测试删除数据
/// 测试删除记录func demoDelete() {    print(Person(dict: ["ID": 1,"age": 20]).deletePerson())}
测试批量插入
/// 测试批量插入数据func insertManyPerson() {    print("开始")    let start = CFabsoluteTimeGetCurrent()    for i in 0..<100000 {        Person(dict: ["name": "lisi-\(i)","age": Int(arc4random_uniform(10)) + 20]).insertPerson()    }    print(CFabsoluteTimeGetCurrent() - start)}

非常耗时,大概需要1分钟左右


查询数据 准备伪代码
/// 加载 Person 对象数组class func loadPersons() -> [Person]? {    // 1. 从数据库获取字典数组    sqliteManager.sharedManager.execRecordSet("SELECT ID,name,age FROM T_Person;")    // 2. 遍历数组,字典转模型    return nil}
sqliteManager中添加查询语句,准备结果集
/// 执行 sql 返回结果集////// - parameter sql: sql////// - returns: 字典数组func execRecordSet(sql: String) -> [[String: AnyObject]]? {    // 1. 准备(预编译) sql    var stmt: copaquePointer = nil    /**        1. 已经打开的数据库句柄        2. 要执行的 sql        3. 以字节为单位的 sql 最大长度,传入 -1 会自动计算        4. sql 语句地址        5. 未使用的指针地址,通常传入 nil    */    if sqlite3_prepare_v2(db,-1,&stmt,nil) != sqlITE_OK {        print("准备 sql 失败")        return nil    }    print("OK")    // 释放语句    sqlite3_finalize(stmt)    return nil}

代码小结

这一部分的工作可以看作是对字符串的 sql 语句进行编译,并且检查是否存在语法问题 编译成功后通过sqlite3_step执行 sql,每执行一次,获取一条记录 通过while循环直至执行完毕 注意,指令执行完毕后需要释放

单步执行

// 2. 单步执行获取结果集内容var index = 0while sqlite3_step(stmt) == sqlITE_ROW {    print(index++)}
遍历stmt中的列数以及每列的列名&数据类型
// 2. 单步执行获取结果集内容while sqlite3_step(stmt) == sqlITE_ROW {    // 1> 结果集列数    let colCount = sqlite3_column_count(stmt)    // 2> 遍历每一列    for col in 0..<colCount {        let cname = sqlite3_column_name(stmt,col)        let name = String(CString: cname,enCoding: NSUTF8StringEnCoding)!        print(name + "\t",appendNewline: false)    }    print("\n",appendNewline: false)}
根据数据类型获取数据
for col in 0..<colCount {    // 1) 字段名    let cname = sqlite3_column_name(stmt,col)    let name = String(CString: cname,enCoding: NSUTF8StringEnCoding)!    // 2) 字段类型    let type = sqlite3_column_type(stmt,col)    // 3) 根据类型获取字段内容    var v: AnyObject? = nil    switch type {    case sqlITE_INTEGER:        v = Int(sqlite3_column_int64(stmt,col))    case sqlITE_float:        v = sqlite3_column_double(stmt,col)    case sqlite3_TEXT:        let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt,col))        v = String(CString: cText,enCoding: NSUTF8StringEnCoding)    case sqlITE_NulL:        v = NSNull()    default:        print("不支持的格式")    }    print(name + "\t" + String(type) + "\t \(v) \t",appendNewline: false)}print("\n",appendNewline: false)
抽取创建结果集代码
/// 从 stmt 获取记录字典////// - parameter stmt: stmt////// - returns: 返回记录集字典private func recordDict(stmt: copaquePointer) -> [String: AnyObject] {    // 1> 结果集列数    let colCount = sqlite3_column_count(stmt)    // 2> 遍历每一列 - 创建字典    var record = [String: AnyObject]()    for col in 0..<colCount {        // 1) 字段名        let cname = sqlite3_column_name(stmt,col)        let name = String(CString: cname,enCoding: NSUTF8StringEnCoding)!        // 2) 字段类型        let type = sqlite3_column_type(stmt,col)        // 3) 根据类型获取字段内容        var v: AnyObject? = nil        switch type {        case sqlITE_INTEGER:            v = Int(sqlite3_column_int64(stmt,col))        case sqlITE_float:            v = sqlite3_column_double(stmt,col)        case sqlite3_TEXT:            let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt,col))            v = String(CString: cText,enCoding: NSUTF8StringEnCoding)        case sqlITE_NulL:            v = NSNull()        default:            print("不支持的格式")        }        record[name] = v    }    return record}
重构后的代码
/// 执行 sql 返回结果集////// - parameter sql: sql////// - returns: 字典数组func execRecordSet(sql: String) -> [[String: AnyObject]]? {    // 1. 准备(预编译) sql    var stmt: copaquePointer = nil    if sqlite3_prepare_v2(db,nil) != sqlITE_OK {        print("准备 sql 失败")        return nil    }    // 2. 单步执行获取结果集内容    // 2.1 结果集    var recordset = [[String: AnyObject]]()    // 2.2 遍历结果集    while sqlite3_step(stmt) == sqlITE_ROW {        recordset.append(recordDict(stmt))    }    // 3. 释放语句    sqlite3_finalize(stmt)    return recordset}
Person模型中加载Person列表
/// 加载 Person 对象数组class func loadPersons() -> [Person]? {    // 1. 从数据库获取字典数组    guard let array = sqliteManager.sharedManager.execRecordSet("SELECT ID,age FROM T_Person;") else {        return nil    }    // 2. 遍历数组,字典转模型    var persons = [Person]()    for dict in array {        persons.append(Person(dict: dict))    }    return persons}

@H_301_1819@ 批量插入

在 sqlite 中如果要批量插入数据,通常需要引入事务的概念

事务 在准备做大规模数据 *** 作前,首先开启一个事务,保存 *** 作前的数据库的状态 开始数据 *** 作 如果数据 *** 作成功,提交事务,让数据库更新到数据 *** 作后的状态 如果数据 *** 作失败,回滚事务,让数据库还原到 *** 作前的状态 事务处理函数
/// 开启事务func beginTransaction() -> Bool {    return execsql("BEGIN TRANSACTION;")}/// 提交事务func commitTransaction() -> Bool {    return execsql("COMMIT TRANSACTION;")}/// 回滚事务func rollBackTransaction() -> Bool {    return execsql("RolLBACK TRANSACTION;")}
修改插入多人记录函数
/// 插入许多人private func insertManyPerson() {    print("开始")    let start = CFabsoluteTimeGetCurrent()    sqliteManager.sharedsqliteManager.beginTransaction()    for i in 0..<100000 {        let person = Person(dict: ["name": "lisi-" + String(i),"age": 18,"height": 1.8])        person.insertPerson()    }    sqliteManager.sharedsqliteManager.commitTransaction()    print("结束 " + String(CFabsoluteTimeGetCurrent() - start))}

测试结果不到 4s

测试回滚
/// 插入许多人private func insertManyPerson() {    print("开始")    let start = CFabsoluteTimeGetCurrent()    sqliteManager.sharedsqliteManager.beginTransaction()    for i in 0..<100000 {        let person = Person(dict: ["name": "lisi-" + String(i),"height": 1.8])        person.insertPerson()        if i == 10000 {            sqliteManager.sharedsqliteManager.rollBackTransaction()            break        }    }    sqliteManager.sharedsqliteManager.commitTransaction()    print("结束 " + String(CFabsoluteTimeGetCurrent() - start))}
批量更新 批量更新函数 - 绑定参数
func batchUpdate(sql: String,params: CVarargType...) -> Bool {    let csql = sql.cStringUsingEnCoding(NSUTF8StringEnCoding)!    var stmt: copaquePointer = nil    if sqlite3_prepare_v2(db,csql,-1,nil) == sqlITE_OK {        // 绑定参数        var col: Int32 = 1        for arg in params {            if arg is Int {                sqlite3_bind_int64(stmt,col,sqlite3_int64(arg as! Int))            } else if arg is Double {                sqlite3_bind_double(stmt,(arg as! Double))            } else if arg is String {                let cStr = (arg as! String).cStringUsingEnCoding(NSUTF8StringEnCoding)                sqlite3_bind_text(stmt,cStr!,sqlITE_TRANSIENT)            } else if arg is NSNull {                sqlite3_bind_null(stmt,col)            }            coL++        }    }    sqlite3_finalize(stmt)    return true}
绑定字符串 如果第5个参数传递NulL或者sqlITE_STATIC常量,sqlite 会假定这块buffer是静态内存,或者客户应用程序会小心的管理和释放这块buffer,所以sqlite放手不管

如果第5个参数传递的是sqlITE_TRANSIENT常量,则sqlite会在内部复制这块buffer的内容。这就允许客户应用程序在调用完bind函数之后,立刻释放这块buffer(或者是一块栈上的buffer在离开作用域之后自动销毁)。sqlite会自动在合适的时机释放它内部复制的这块buffer

由于在 sqlite.h 中sqlITE_TRANSIENT是以宏的形式定义的,而在 swift 中无法直接利用宏传递函数指针,因此需要使用以下代码转换一下

swift 1.2
private let sqlITE_TRANSIENT = sqlite3_destructor_type(copaquePointer(bitPattern: -1)) 
swift 2.0
private let sqlITE_TRANSIENT = unsafeBitCast(-1,sqlite3_destructor_type.self) 
而绑定字符串的函数必须写成(OC中可以使用NulL,是因为OC中以 @"" 定义的函数都是保存在静态区的)
sqlite3_bind_text(stmt,index,cStr,sqlITE_TRANSIENT)
单步执行
var result = trueif sqlite3_step(stmt) != sqlITE_DONE {    print("插入错误")    result = false}// 语句复位if sqlite3_reset(stmt) != sqlITE_OK {    print("语句复位错误")    result = false}sqlite3_finalize(stmt)return result

注意:执行结束后,一定要对语句进行复位,以便后续查询语句能够继续执行

函数小结 列数的计数从 1 开始 对于数据更新 *** 作,单步执行正确的结果是sqlITE_DONE 每单步执行之后,需要做一次reset *** 作 使用预编译 sql 批量插入数据 批量插入数据
/// 批量插入private func batchInsert() {    print("开始")    let start = CFabsoluteTimeGetCurrent()    let manager = sqliteManager.sharedsqliteManager    let sql = "INSERT INTO T_Person (name,height) VALUES (?,?,?);"    // 开启事务    manager.beginTransaction()    for _ in 0..<10000 {        if !manager.batchUpdate(sql,params: "zhangsan",18,1.8) {            manager.rollBackTransaction()            break        }    }    manager.commitTransaction()    print("结束 " + String(CFabsoluteTimeGetCurrent() - start))}

运行测试,执行结果只需要 0.1s

多线程 定义队列
///  *** 作队列private let queue = dispatch_queue_create("com.itheima.sqlite",disPATCH_QUEUE_SERIAL)
队列执行
/// 队列更新////// :param: action 在后台执行的任务func queueUpdate(action: (manager: sqliteManager) -> ()) {    dispatch_async(queue) { [uNowned self] in        // 1. 开启事务        self.beginTransaction()        action(manager: self)        // 2. 提交事务        self.commitTransaction()    }}
测试后台更新
private func queueUpdate() {    print("开始")    let start = CFabsoluteTimeGetCurrent()    sqliteManager.sharedsqliteManager.queueUpdate { (manager) -> () in        let sql = "INSERT INTO T_Person (name,?);"        for i in 0..<10000 {            if !manager.batchUpdate(sql,1.8) {                manager.rollBackTransaction()                break            }            if i == 1000 {                manager.rollBackTransaction()                break            }        }        print(NSThread.currentThread())        print("结束 " + String(CFabsoluteTimeGetCurrent() - start))    }}

注意:sqlite 数据库不允许同时并发写入输入,如果用多线程,也必须使用串行队列进行 *** 作


FMDB 使用框架 官网地址

https://github.com/ccgus/fmdb

直接拖拽 将 fmdb 文件夹拖入项目 建立桥接文件 将 Swift extensions 拖入项目 Podfile 不推荐
use_frameworks!pod 'FMDB',:git => 'https://github.com/robertmryan/fmdb.git'
代码演练 除了查询都使用executeUpdate 查询使用executequery
let documentsFolder = NSSearchPathForDirectorIEsInDomains(.documentDirectory,.UserDomainMask,true)[0] as Stringlet path = documentsFolder.stringByAppendingPathComponent("test.sqlite")let database = FMDatabase(path: path)if !database.open() {    println("Unable to open database")    return}if !database.executeUpdate("create table test(x text,y text,z text)",withArgumentsInArray: nil) {    println("create table Failed: \(database.lastErrorMessage())")}if !database.executeUpdate("insert into test (x,y,z) values (?,?)",withArgumentsInArray: ["a","b","c"]) {    println("insert 1 table Failed: \(database.lastErrorMessage())")}if !database.executeUpdate("insert into test (x,withArgumentsInArray: ["e","f","g"]) {    println("insert 2 table Failed: \(database.lastErrorMessage())")}if let rs = database.executequery("select x,z from test",withArgumentsInArray: nil) {    while rs.next() {        let x = rs.stringForColumn("x")        let y = rs.stringForColumn("y")        let z = rs.stringForColumn("z")        println("x = \(x); y = \(y); z = \(z)")    }} else {    println("select Failed: \(database.lastErrorMessage())")}database.close()
队列演练
let queue = FMDatabaseQueue(path: "/Users/liufan/Desktop/my.db")let sql = "insert into t_person (name,age) VALUES (?,?);"queue.inTransaction { (db,rollBack) -> VoID in    db.executeUpdate(sql,"lisi",28)    db.executeUpdate(sql,"wangwu",48)    rollBack.memory = true}queue.inDatabase { (db) -> VoID in    if let result = db.executequery("select * from t_person") {        while result.next() {            let name = result.objectForColumnname("name")            let age = result.intForColumn("age")            print("\(name) \(age)")        }    }}

要设置 rollBack 可以使用rollBack.memory = true

总结

以上是内存溢出为你收集整理的说说SQLite在移动开发的那些事儿全部内容,希望文章能够帮你解决说说SQLite在移动开发的那些事儿所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1164704.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存