未命名标题shu

数据表定义语句(DDL)

创建表:

create table if not exists <biaoming> (id integer primary key autoincrement,name text not NULL, age integer default 60)

删除表:

drop table if exists <biaoming>

更改表名:

alter table <biaoming> rename to <xinbiaoming>

给表增加列:

alter table <biaoming> add column <lieming> name text <zhibiaofu>

数据表操作语句(DML)

增加:

insert into <biaoming> (name, age,score) values {'xiaowang',90,80}

修改:

update <> set name = 'xiaohong',age = 20

update <> set score = 30 where id > 30

删除:

delete from <> where age is 18

DQL:查询语句

select name, age from <>

select * from <>

统计:

记录所有age不为空的个数(记录)select count(age) from <>

记录某个字段平均值 select avg(age) from <>

求和:sum zuida:max zuixiao:min

排序:

select *from <> order by score ASC(升序) 或者用 DESC(降序)

select *from <> order by score ASC,age DESC

分页:

select * from <> limit 1,3 1表示跳过1条,3表示跳过3条

多表查询:

OC中代码:

创建数据库

    //参数1.数据库文件的路径 2.数据库对象,要打开的数据库
    //返回值表示操作的状态码
    int result = sqlite3_open(filename, &_db);
    if (result == SQLITE_OK)
    {
        NSLog(@"数据库打开成功");
        return YES;
    }
    else
    {
        NSLog(@"数据库打开失败");
        //sqlite3_close 关闭数据库的方法
        sqlite3_close(_db);
        return NO;
    }

创建表
    char *error = nil;
    //sqlite3_exec对数据库的操作:创建表,增删改,都建议用这个方法,查建议用其他的
    //参数 1.数据库对象 2.sql语句 3.回调函数nil 4.回调函数的参数nil
    if (sqlite3_exec(_db, [str UTF8String], nil, nil, &error)==SQLITE_OK)
    {
        NSLog(@"创建表成功");
    }
    else
    {
        NSLog(@"创建表失败:%s",error);
    }

增删改查

//第一种方式sqlite3_exec

//sql为相关的增删改语句
sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK

//另一种方式,预处理语句sqlite3_prepare_v2

let prepareSql = "INSERT INTO \(tableName)(\(columnNames)) values (\(valuesStr))"

        var stmt: COpaquePointer = nil

        // 预处理SQL语句, 并生成 "语句句柄" , 后续会使用这样的语句句柄绑定数值, 并执行

        if sqlite3_prepare_v2(db, prepareSql, -1, &stmt, nil) != SQLITE_OK
        {
            print("预处理失败")
            // 释放语句资源
            sqlite3_finalize(stmt)
            return false
        }

        var index: Int32 = 1

        for obj in values
        {

            if obj is Int
            {
                let temp: sqlite_int64 = obj as! sqlite_int64
                sqlite3_bind_int64(stmt, index, temp)
            } else if obj is Double
            {
                sqlite3_bind_double(stmt, index, obj as! Double)
            }else if obj is String
            {
                /**
                 第5个参数
                 此参数有两个常数,SQLITE_STATIC告诉sqlite3_bind_text函数字符串为常量,可以放心使用;
                 而SQLITE_TRANSIENT会使得sqlite3_bind_text函数对字符串做一份拷贝。
                一般使用这两个常量参数来调用sqlite3_bind_text。
                 */
                sqlite3_bind_text(stmt, index, obj as! String, -1, SQLITE_TRANSIENT)

            }else {
                continue
            }

            index++

        }

        var result: Bool = false
        if sqlite3_step(stmt) == SQLITE_DONE
        {
            print("插入成功")
            result = true
        }else
        {
            print("插入失败")
            result = false

        }

        // 将语句复位
        if sqlite3_reset(stmt) != SQLITE_OK
        {
            print("复位失败")
            result = false
        }

        // 释放语句
        sqlite3_finalize(stmt)

        return result

处理大数据耗时问题

插入10000条数据

sqlite_exec 10000 5.8080689907074
sqlite_prepare 10000 5.93309998512268
sqlite_prepare 分解后, 准备1次, 多次绑定/重置, 一次释放 5.11254101991653
分析结果
所以: 如果执行单条语句的话, 两者效率几乎一致
如果执行多条语句, 建议使用"准备语句"
两者区别:
sqlite_exec 函数是对"准备语句"的封装 (预处理语句->绑定参数->执行语句->重置语句->释放语句)
如果需要绑定二进制数据, 就必须要使用"准备语句了"
sqlite_exec 用法相对简单

整体耗时, 依然达到5秒左右, 非常庞大
原因: 因为sqlite3_exec, 或者 sqlite3_step 执行语句时, 都会自动开启事务-> 执行语句 -> 提交事务 这样的流程, 所以造成了, 多次开启和提交事务, 这个是非常耗时的操作
解决方案: 手动开启和提交事务即可, 这样 系统就不会自动开启事务和提交事务了

代码:


XMGSQLTool.shareInstance.beginTransaction()
for _ in 0...9999 {
stu.insertStudent()
}
XMGSQLTool.shareInstance.commitTransaction()

/** 开启事务 */
    func beginTransaction() -> Bool
    {
        let sql = "BEGIN TRANSACTION"
        return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
    }

    /** 提交事务 */
    func commitTransaction() -> Bool
    {
        let sql = "COMMIT TRANSACTION"
        return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
    }

/** 回滚事务*/
    func rollBackTransaction() -> Bool
    {
        let sql = "ROLLBACK TRANSACTION"
        return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
    }

开启事务BEGIN TRANSACTION
提交事务COMMIT TRANSACTION
回滚事务ROLLBACK TRANSACTION

查询的两种方式

        let selectSql = "select * from t_student"

        // 方式1:
        // 参数1: 一个打开的数据库
        // 参数2: 需要执行的SQL语句
        // 参数3: 查询结果回调(执行0次或多次)
            // 参数1: 参数4的值
            // 参数2: 列的个数
            // 参数3: 结果值的数组
            // 参数4: 所有列的名称数组
            // 返回值: 0代表继续执行一致到结束, 1代表执行一次
        // 参数4: 回调函数的第一个值
        // 参数5: 错误信息
        sqlite3_exec(db, selectSql, { (parameter: UnsafeMutablePointer<Void>, columnCount: Int32, values: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>, columnNames: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32 in

                let count = Int(columnCount)
                for i: Int in 0..<count
                {
                    let column = columnNames[i]
                    let columnStr = String(CString: column, encoding: NSUTF8StringEncoding)

                    let value = values[i]
                    let valueStr = String(CString: value, encoding: NSUTF8StringEncoding)
                    print(columnStr! + "= " + valueStr!)
                }

                return 0
            }, nil, nil)

            // 方式2:
//        var stmt: COpaquePointer = nil
//        if sqlite3_prepare(db, selectSql, -1, &stmt, nil) != SQLITE_OK
//        {
//            print("预处理失败")
//            return
//        }
//
//        // 因为查询语句中没有占位?, 所以, 可以省略"绑定步骤"
//        // 执行语句
//        // sqlite3_step, 当使用这个方法时, 执行完毕后, 会自动跳到结果集的下一行, 如果依然有记录就返回SQLITE_ROW,
//       while sqlite3_step(stmt) == SQLITE_ROW
//       {
//        let columnCount = sqlite3_column_count(stmt)
//
//        for i in 0..<columnCount
//        {
//
//            //  获取列的类型
//            let type = sqlite3_column_type(stmt, i)
//
//            if type == SQLITE_TEXT
//            {
//                let text = UnsafePointer<Int8>(sqlite3_column_text(stmt, i))
//                let str = String(CString: text, encoding: NSUTF8StringEncoding)
//                print(str)
//            }
//
//        }
//
//        }
//
//        sqlite3_finalize(stmt)

FMDB使用:

优势:1.封装 2.提供了多线程访问数据方式

三个主要的类:

FMDatabase:是一个提供 SQLite 数据库的类,用于执行 SQL 语句。
FMResultSet:用在 FMDatabase 中执行查询的结果的类。
FMDatabaseQueue:在多线程下查询和更新数据库用到的类。

数据库创建

FMDatabase 是通过一个 SQLite 数据库文件路径创建的,此路径可以是以下三者之一:

一个文件的系统路径。磁盘中可以不存在此文件,因为如果不存在会自动为你创建。
一个空的字符串 @""。会在临时位置创建一个空的数据库,当 FMDatabase 连接关闭时,该数据库会被删除。
NULL。会在内存中创建一个数据库,当 FMDatabase 连接关闭时,该数据库会被销毁。

推荐文章:

[an example]http://www.jianshu.com/p/d60ee3c85d63

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容