第十二篇Swift----Sqlite的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十二篇Swift----Sqlite的使用相关的知识,希望对你有一定的参考价值。

 

import UIKit

class SQLiteManager: NSObject {

    private static let manager: SQLiteManager = SQLiteManager()
    /// 单粒
    class func shareManager() ->SQLiteManager {
        return manager
    }
    
    // 数据库对象
    private var db:COpaquePointer = nil
    
    // 创建一个串行队列
    private let dbQueue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_SERIAL)
    
    func execQueueSQL(action: (manager: SQLiteManager)->())
    {
        // 1.开启一个子线程
        dispatch_async(dbQueue) { () -> Void in
            print(NSThread.currentThread())
            // 2.执行闭包
            action(manager: self)
        }
    }
    
    /**
    打开数据库
    
    :param: SQLiteName 数据库名称
    */
    func openDB(SQLiteName: String)
    {
        // 0.拿到数据库的路径
        let path = SQLiteName.docDir()
        print(path)
        let cPath = path.cStringUsingEncoding(NSUTF8StringEncoding)!
        // 1.打开数据库
        /*
        1.需要打开的数据库文件的路径, C语言字符串
        2.打开之后的数据库对象 (指针), 以后所有的数据库操作, 都必须要拿到这个指针才能进行相关操作
        */
        // open方法特点: 如果指定路径对应的数据库文件已经存在, 就会直接打开
        //              如果指定路径对应的数据库文件不存在, 就会创建一个新的
        if sqlite3_open(cPath, &db) != SQLITE_OK
        {
            print("打开数据库失败")
            return
        }
        
        // 2.创建表
        if creatTable()
        {
            print("创建表成功")
        }else
        {
            print("创建表失败")
        }
    }
    
    private func creatTable() -> Bool
    {
        // 1.编写SQL语句
        // 建议: 在开发中编写SQL语句, 如果语句过长, 不要写在一行
        // 开发技巧: 在做数据库开发时, 如果遇到错误, 可以先将SQL打印出来, 拷贝到PC工具中验证之后再进行调试
        let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
        "id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
        "name TEXT, \n" +
        "age INTEGER \n" +
        "); \n"
//        print(sql)
        // 2.执行SQL语句
        return execSQL(sql)
    }
    
    /**
    执行除查询以外的SQL语句
    
    :param: sql 需要执行的SQL语句
    
    :returns: 是否执行成功 true执行成功 false执行失败
    */
    func execSQL(sql: String) -> Bool
    {
        // 0.将Swift字符串转换为C语言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 在SQLite3中, 除了查询意外(创建/删除/新增/更新)都使用同一个函数
        /*
        1. 已经打开的数据库对象
        2. 需要执行的SQL语句, C语言字符串
        3. 执行SQL语句之后的回调, 一般传nil
        4. 是第三个参数的第一个参数, 一般传nil
        5. 错误信息, 一般传nil
        */
        if sqlite3_exec(db, cSQL, nil, nil, nil) != SQLITE_OK
        {
            return false
        }
        return true
    }
    
    /**
    查询所有的数据
    :returns: 查询到的字典数组
    */
    func execRecordSQL(sql: String) ->[[String: AnyObject]]
    {
        // 0.将Swift字符串转换为C语言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 1.准备数据
        // 准备: 理解为预编译SQL语句, 检测里面是否有错误等等, 它可以提供性能
        /*
        1.已经开打的数据库对象
        2.需要执行的SQL语句
        3.需要执行的SQL语句的长度, 传入-1系统自动计算
        4.预编译之后的句柄, 已经要想取出数据, 就需要这个句柄
        5. 一般传nil
        */
        var stmt: COpaquePointer = nil
        if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK
        {
            print("准备失败")
        }
        
        // 准备成功
        var records = [[String: AnyObject]]()
        
        // 2.查询数据
        // sqlite3_step代表取出一条数据, 如果取到了数据就会返回SQLITE_ROW
        while sqlite3_step(stmt) == SQLITE_ROW
        {
            // 获取一条记录的数据
            let record = recordWithStmt(stmt)
            // 将当前获取到的这一条记录添加到数组中
            records.append(record)
        }
        
        // 返回查询到的数据
        return records
    }
    
    /**
    获取一条记录的值
    
    :param: stmt 预编译好的SQL语句
    
    :returns: 字典
    */
    private func recordWithStmt(stmt: COpaquePointer) ->[String: AnyObject]
    {
        // 2.1拿到当前这条数据所有的列
        let count = sqlite3_column_count(stmt)
        //            print(count)
        // 定义字典存储查询到的数据
        var record  = [String: AnyObject]()
        
        for index in 0..<count
        {
            // 2.2拿到每一列的名称
            let cName = sqlite3_column_name(stmt, index)
            let name = String(CString: cName, encoding: NSUTF8StringEncoding)!
            //                print(name)
            // 2.3拿到每一列的类型 SQLITE_INTEGER
            let type = sqlite3_column_type(stmt, index)
//                print("name = \(name) , type = \(type)")
            
            switch type
            {
            case SQLITE_INTEGER:
                // 整形
                let num = sqlite3_column_int64(stmt, index)
                record[name] = Int(num)
            case SQLITE_FLOAT:
                // 浮点型
                let double = sqlite3_column_double(stmt, index)
                record[name] = Double(double)
            case SQLITE3_TEXT:
                // 文本类型
                let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, index))
                let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!
                record[name] = text
            case SQLITE_NULL:
                // 空类型
                record[name] = NSNull()
            default:
                // 二进制类型 SQLITE_BLOB
                // 一般情况下, 不会往数据库中存储二进制数据
                print("")
            }
        }
        return record
    }
    
}

 

使用事务插入数据:

       let manager = SQLiteManager.shareManager()
        
        // 开启事务
        manager.beginTransaction()
        
        for i in 0..<10000
        {
            let p = Person(dict: ["name": "zs + \(i)", "age": 3 + i])
            p.insertPerson()
            
            if i == 1000
            {
                manager.rollbackTransaction()
                // 注意点: 回滚之后一定要跳出循环停止更新
                break
            }
        }
        
        // 提交事务
        manager.commitTransaction()

 

预编译绑定:

    //1、打开数据库  
    sqlite3 *db = [self sqlite3_open_database];  
    //2、建立预编译语句对象并编译  
    charchar *sql = "INSERT INTO student(name,age) VALUES(?,?)";//?为占位符,代表此处将来用变量值替换  
    //2.1、准备预编译语句对象  
    sqlite3_stmt *stmt = NULL;  
    //2.2、预编译sql语句  
    int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);  
    //2.3、预编译成功,绑定值  
    if (result == SQLITE_OK) {  
        //绑定界面数据到预编译sql语句中  
        sqlite3_bind_text(stmt, 1, [self.txtName.text UTF8String], -1, NULL);  
        sqlite3_bind_int(stmt, 2, [self.txtAge.text intValue]);  
        //3、执行预编译语句对象,4、使用结果  
        result = sqlite3_step(stmt);  
        if (result == SQLITE_DONE) {  
            [self myAlert:@"插入数据成功!"];  
        } else {  
            [self myAlert:@"插入数据失败!"];  
        }  
    }  
    //5、销毁预编译语句对象,关闭数据库  
    sqlite3_finalize(stmt);  
    sqlite3_close(db); 

 

以上是关于第十二篇Swift----Sqlite的使用的主要内容,如果未能解决你的问题,请参考以下文章

R实战 第十二篇:随机数

第十二篇:为用户设计良好的接口

第十二篇:编程范式

第十二篇 JavaScript(简称JS) 实现显示与隐藏

开始写游戏 --- 第十二篇

Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇)