您的位置:首页 > 移动开发 > Swift

Swift 中使用 SQLite——查询数据

2016-03-16 01:20 337 查看
本文主要介绍如何查询 SQLite 结果集,以及封装
SQLite 的操作方法。

准备测试代码

[code]/// 从数据库中加载 person 数组
class func persons() -> [Person]? {

    // 1. 准备 SQL
    let sql = "SELECT id, name, age, height FROM T_Person;"

    // 2. 访问数据库

    // 3. 返回结果
    return nil
}

SQLiteManager
中添加查询语句,准备结果集

[code]/// 执行 SQL 返回查询结果集
///
/// - parameter sql: 任意给定的 SELETE 查询 SQL
func execRecordSet(sql: String) {

    // 1. 预编译 SQL
    /**
        参数

        1. 已经打开的数据库句柄
        2. 要执行的 SQL
        3. 以字节为单位的 SQL 最大长度,传入 -1 会自动计算
        4. SQL 语句句柄
            - 后续针对当前查询结果的操作全部基于此句柄
            - 需要调用 sqlite3_finalize 释放
        5. 未使用的指针地址,通常传入 nil
    */
    var stmt: COpaquePointer = nil
    if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
        print("SQL 错误")
        return
    }

    print("SQL 正确")
    // 2. 遍历集合

    // 3. 释放语句句柄 - 很重要,否则会内容泄漏
    sqlite3_finalize(stmt)
}



代码小结

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

单步执行

[code]// 2. 单步执行获取结果集内容
var row = 0
while sqlite3_step(stmt) == SQLITE_ROW {
    print("记录 \(row++)")
}

新建函数负责从
stmt
中获取一条完整的记录

[code]/// 从 stmt 中获取一条完整的记录
///
/// - parameter stmt: stmt
private func record(stmt: COpaquePointer) {
    print("记录")
}

获取单条记录

所有函数都是以
sqlite3_column_
开始

获取
列数


[code]// 查询结果列数
let colCount = sqlite3_column_count(stmt)
print("列数 \(colCount)")


遍历每一列获取对应的
列名
数据类型


[code]// 遍历每一列
for col in 0..<colCount {
    // 列名
    let cName = sqlite3_column_name(stmt, col)
    let name = String(CString: cName, encoding: NSUTF8StringEncoding) ?? ""
    // 数据类型
    let type = sqlite3_column_type(stmt, col)

    print("列名 \(name) 值 \(value)")
}

根据不同的数据类型转换对应的数值

小数

[code]var value: AnyObject?
switch type {
case SQLITE_FLOAT:
    value = sqlite3_column_double(stmt, col)
default:
    print("不支持的数据类型")
}

print("列名 \(name) 值 \(value)")


整数

[code]case SQLITE_INTEGER:
    value = Int(sqlite3_column_int64(stmt, col))


字符串

[code]case SQLITE3_TEXT:
    let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, col))
    value = String(CString: cText, encoding: NSUTF8StringEncoding)


空值

[code]case SQLITE_NULL:
    value = NSNull()


增加返回值和字典,调整后的代码如下:

[code]/// 从 stmt 中获取当前记录的完整内容
///
/// - parameter stmt: stmt 句柄
private func record(stmt: COpaquePointer) -> [String: AnyObject] {

    // 1. 获取查询结果列数
    let colCount = sqlite3_column_count(stmt)

    // 单条记录字典
    var row = [String: AnyObject]()

    // 2. 遍历所有列,获取每一列的信息
    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 value: AnyObject?
        switch(type) {
        case SQLITE_FLOAT:
            value = sqlite3_column_double(stmt, col)
        case SQLITE_INTEGER:
            value = Int(sqlite3_column_int64(stmt, col))
        case SQLITE3_TEXT:
            let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, col))
            value = String(CString: cText, encoding: NSUTF8StringEncoding)
        case SQLITE_NULL:
            value = NSNull()
        default:
            print("不支持的数据类型")
        }

//            print("列名 \(name) 值 \(value)")
        row[name] = value ?? NSNull()
    }

    return row
}

完善
execRecordSet
函数

完善
execRecordSet
函数

[code]/// 执行 SQL 返回查询结果集
///
/// - parameter sql: 任意给定的 SELETE 查询 SQL
func execRecordSet(sql: String) -> [[String: AnyObject]]? {

    // 1. 预编译 SQL
    /**
        参数

        1. 已经打开的数据库句柄
        2. 要执行的 SQL
        3. 以字节为单位的 SQL 最大长度,传入 -1 会自动计算
        4. SQL 语句句柄
            - 后续针对当前查询结果的操作全部基于此句柄
            - 需要调用 sqlite3_finalize 释放
        5. 未使用的指针地址,通常传入 nil
    */
    var stmt: COpaquePointer = nil
    if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
        print("SQL 错误")
        return nil
    }

    // 创建结果数组
    var rows = [[String: AnyObject]]()

    // 2. 遍历集合
    while sqlite3_step(stmt) == SQLITE_ROW {
        // 将单条记录字典添加到结果数组中
        rows.append(record(stmt))
    }

    // 3. 释放语句句柄 - 很重要,否则会内容泄漏
    sqlite3_finalize(stmt)

    // 4. 返回结果数组
    return rows
}


Person
模型中加载
Person
列表

[code]/// 从数据库中加载 person 数组
class func persons() -> [Person]? {

    // 1. 准备 SQL
    let sql = "SELECT id, name, age, height FROM T_Person;"

    // 2. 访问数据库获得字典数组
    guard let rows = SQLiteManager.sharedManager.execRecordSet(sql) else {
        return nil
    }

    // 3. 遍历字典数组 - 字典转模型
    var arrayM = [Person]()
    for row in rows {
        arrayM.append(Person(dict: row))
    }

    // 4. 返回结果集合
    return arrayM
}


测试代码

[code]print((Person.persons() ?? []) as NSArray)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: