第十二篇、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); 
时间: 2024-10-12 15:11:36

第十二篇、Swift----Sqlite的使用的相关文章

Python开发【第二十二篇】:Web框架之Django【进阶】

Python开发[第二十二篇]:Web框架之Django[进阶] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 新随笔 联系 订阅 管理 随笔-124  文章-127  评论-205 Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻

SaltStack 学习笔记 - 第十二篇: SaltStack Web 界面

SaltStack 有自身的用python开发的web界面halite,好处是基于python,可以跟salt的api无缝配合,确定就比较明显,需要个性化对web界面进行定制的会比较麻烦,如果喜欢体验该界面的可以参考下面的文章  http://rfyiamcool.blog.51cto.com/1030776/1275443/ 我是运用另一个python+php来进行web开发,具体需要的工具有在我的另一篇文章里面介绍过,这里再重新进行整个开发介绍 首先介绍php 跟python通信的工具 pp

第二十二篇:再写Windows驱动,再玩Windbg---NET

2011年到现在,就没再怎么搞过Windows驱动了. 最近, 由于项目需要, 试着改一改一个显卡驱动(KMDOD), 从实践上证明, 我在理论上对一个驱动的架构的正确与否.(USB Display = KMDOD + AVStream). 其中, KMDOD是完成显示的部分功能, 完成其中的VidPN(Video present network), 将驱动中原来的POST物理设备转变为USB物理设备. 而AVStream之所以这样提出, 完成是由于USB Video class的启发, 要不然

SQL Server 索引的图形界面操作 &lt;第十二篇&gt;

一.索引的图形界面操作 SQL Server非常强大的就是图形界面操作.关于索引方面也一样那么强大,很多操作比如说重建索引啊,查看各种统计信息啊,都能够通过图形界面快速查看和操作,下面来看看SQL Server索引方面的GUI操作. 二.索引统计信息的图形界面操作 SQL Server 索引的图形界面操作 <第十二篇>

第二十二篇 信念

第二十二篇  信念 "信念"能带给一个人无穷的力量,这些力量可以支撑自己走过漫长的人生.一个人如果没有信念,就很难找到自己的人生方向,所以"信念"也可以理解为希望. 信念可以给到我们希望,也可以给到我们力量,所以一个人的信念会影响到自己的整个人生.当然信念也有好坏之分,好的信念能让自己积极向上.不畏艰难:坏的信念会让我们不思进取.随波逐流.这两种不同的信念会给到我们两种完全不同的人生,就看亲人们如何作出正确的选择. 一个人活在世上,可以选择走正确的人生道路,依靠好的

解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)

解剖SQLSERVER 第十二篇   OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发工作中,我终于将OrcaMDF 压缩功能分支合并到主分支这意味着OrcaMDF 现在正式支持数据行压缩功能 支持的数据类型实现行压缩需要我修改几乎所有已实现的数据类型以将他们作为压缩存储.integer类型被压缩了,decimal类型变成可变长度,而可变长度类型基本上都被截断了进而用0来填补.所有先

python学习[第十二篇] 数据类型之 集合

python学习[第十二篇] 数据类型之 集合 集合概念 python中集合是一组无序排列的哈希值.集合分为两种可变集合(set)和不可变集合(frozenset) 对可变集合可以修改和删除元素,对于不可变集合不允许.可变集合是不可以哈希的,因此既不能用作字典的键,也不能做其他集合的元素. 集合的增删改查 集合的创建于赋值 集合与列表([]) 和字典({})不同,集合没有特别的语法格式.列表和字典可以通过他们自己的工厂方法创建,这也是集合的唯一的创建方式.set()和frozenset() #创

Windows界面编程第十二篇 位图显示特效 飞入效果与伸展效果

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8696726 欢迎关注微博:http://weibo.com/MoreWindows Windows界面编程之位图显示特效系列目录: 1. <Windows界面编程第九篇位图显示特效交错效果> http:/

跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探

SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明,本系列教程全采用以上版本 前面我们在聊服务网关Zuul的时候提到了Gateway,那么Zuul和Gateway都是服务网关,这两个有什么区别呢? 1. Zuul和Gateway的恩怨情仇 1.1 背景 Zuul是Netflix开源的一个项目,Spring只是将Zuul集成在了Spring

Egret入门学习日记 --- 第二十二篇(书中 9.7~9.8 节 内容)

第二十二篇(书中 9.7~9.8 节 内容) 开始 9.7节 内容. 重点: 1.进度条ProgressBar的声明和使用. 操作: 1.进度条ProgressBar的声明和使用. 现在真的轻车熟路了,很简单.无非就是设置一下最大值,当前值的属性. 然后,事件监听的话,也是一样的.只不过事件名字的话,我就选书中这个事件吧. 可惜不能发动图,不然你们就可以看到这个进度条,每帧+1的速度前进. 当然,如果你想换自定义皮肤,还是老规矩,去找默认的 EXML 文件. 然后,怎么换素材,就按照自己喜欢的换