拿走即用之FMDB

FMDB

框架使用(作者离职,求一份工作)

  • 将 fmdb 文件夹拖入项目
  • 建立桥接文件
  • 将 Swift extensions 拖入项目
  • 添加 libsqlite3.tdb

FMDB 架构图

FMDB.png

代码演练之创建数据库到对数据的增删改查

import Foundation

/// 数据库名称
private let dbname = "my.db"

class SQLiteManager {
    
    /// 单例 - 全局访问点
    static let sharedManager = SQLiteManager()
    
    /// 全局数据库操作队列 对于常量而言,有一次设置数值的机会
    let queue: FMDatabaseQueue
    
    // 使用 private 可以保证外界统一通过 sharedManager 访问
    private init() {
        print("基本准备工作")
        
        var path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
        path = (path as NSString).stringByAppendingPathComponent(dbname)
        
        print(path)
        
        // 1. 打开数据库
        /**
            参数:数据库的全路径
            返回:数据库操作队列,全局数据库的访问入口
            特点:如果数据库存在,打开数据库,建立队列
                 如果数据库不存在,新建数据库,建立队列
        */
        queue = FMDatabaseQueue(path: path)
        
        // 2. 创建数据表
        createTables()
    }
    
    //MARK: - 增加数据
    /// 使用`预编译` SQL 插入数据
    private func insertPerson4(name: String,age:NSInteger,height:Double) {
        
        // 1. 准备 SQL
        /**
        特点:
        1> 使用 ? 作为参数的占位符号
        2> 提前编译 SQL,确认语法正确
        3> 在真正执行 SQL 的时候,使用参数,替换 `?`
        4> 预编译 SQL 中的字符串,不需要使用单引号 '
        
        更加安全,可以留存用户输入的所有内容!推荐使用!
        */
        let sql = "INSERT INTO T_Person (name, age, height) VALUES (?, ?, ?);"
        
        // 2. 执行 sql
        queue.inDatabase { (db) -> Void in
            
            // 执行单条语句更安全
            do {
                try db.executeUpdate(sql, name, age, height)
            } catch {
                print("数据插入失败 \\(error)")
            }
        }
    }
    
    // MARK: - 删除数据
    private func deletePerson(id: Int) {
        
        let sql = "DELETE FROM T_Person WHERE id = :id;"
        
        queue.inDatabase { (db) -> Void in
            
            if db.executeUpdate(sql, withParameterDictionary: ["id": id]) {
                print("删除成功 删除的数据行数为 \\(db.changes())")
            } else {
                print("删除失败")
            }
        }
    }
    
    // MARK: - 更新数据
    private func updatePerson(dict: [String: AnyObject]) {
        
        // 如果条件不符合,会正常执行,不会报错
        var sql = "UPDATE T_Person set name = :name, age = :age, height = :height \\n"
        sql += "WHERE id = :id;"
        
        queue.inDatabase { (db) -> Void in
            
            if db.executeUpdate(sql, withParameterDictionary: dict) {
                print("更新成功 更新的数据行数为 \\(db.changes())")
            } else {
                print("更新失败")
            }
        }
    }
//MARK: - 查询数据
    /// 执行 SQL 返回结果集合[字典数组]
    ///
    /// - parameter sql: 要执行的 SQL
    ///
    /// - returns: 返回查询结果,如果 SQL 语法错误,返回 nil
    func execRecordSet(sql: String) -> [[String: AnyObject]]? {
        
        // `定义`字典数组,var 的可选项的默认值是 nil
        var recordSet: [[String: AnyObject]]?
        
        queue.inDatabase { (db) -> Void in
            
            guard let rs = try? db.executeQuery(sql) else {
                print("SQL 语句错误")
                return
            }
            
            // 实例化字典
            recordSet = [[String: AnyObject]]()
            
            while rs.next() {
                // 1. 知道查询结果的列数
                let colCount = rs.columnCount()
                
                // 2. 定义一行的字典
                var row = [String: AnyObject]()
                
                for col in 0..<colCount {
                    // 1> 获得列名
                    let name = rs.columnNameForIndex(col)
                    
                    // 2> 获得值
                    let value = rs.objectForColumnIndex(col)
                    
                    // 3> 设置字典
                    row[name] = value
                }
                
                // 添加到数组
                recordSet!.append(row)
            }
        }
        
        // 返回查询结果
        return recordSet
    }
    
    /// 建立数据表
    private func createTables() {
        
        // 1. 准备 sql
        let path = NSBundle.mainBundle().pathForResource("db.sql", ofType: nil)!
        
        let sql = try! String(contentsOfFile: path)
        
        print(sql)
        
        // 2. 执行 sql,串行队列同步执行,保证数据安全
        queue.inDatabase { (db) -> Void in
            // 执行 `单条` SQL - 不适合创建数据表,因为一次只能执行一条
            // 如果有多个表,会很麻烦
//            do {
//                try db.executeUpdate(sql)
//            } catch {
//                print("创建数据表失败 \\(error)")
//            }
            
            // 执行`多条` SQL - 仅适合用于创建数据表,可以一次创建多个表
            if db.executeStatements(sql) {
                print("创表成功")
            } else {
                print("创表失败")
            }

            // 使用 FMDB 时,一定注意不要嵌套使用,否则死锁!
//            self.queue.inDatabase({ (db) -> Void in
//                
//            })
        }
        
        print("come here")
    }
}

sql常用语句

创建表

CREATE TABLE IF NOT EXISTS "T_Person" (
      "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
      "name" TEXT,
      "age" INTEGER,
      "heigth" REAL
)
//下边是sqllite编译器里边的语句

/*简单约束*/
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,
     name TEXT,
     age INTEGER,
     score REAL
);

/*添加主键*/
CREATE TABLE IF NOT EXISTS t_student
(
     id INTEGER,
     name TEXT,
     age INTEGER,
     score REAL,
     PRIMARY KEY(id)
);

查询

  /*分页*/
 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;
修改
 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;

插入

 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);

删除表

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

推荐阅读更多精彩内容