FMDB常用操作

项目中比较多的用到了数据库,整理一下常用的数据库操作

简介

简单整理一些FMDB的一些常用操作.
需要了解的概念包括但不限于外连接,表别名,唯一键,升序,游标,like,between and,not null,unique,default,check,primary key, foreing key,union等等,更多查看sqlite关键字

CRUD,连表查询,索引,事务,回滚

  1. CRUD
    创建数据库文件,一般有两种方法,一是新建一个文件,然后后缀名修改为自定义后缀,然后直接拖到项目的main bundle,还有一种是获取当前app的沙盒路径,然后在目录下面新建一个文件作为数据库文件.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // create
    // 第二种方法示例:
    // 全局db路径
    _dbPath = [path stringByAppendingPathComponent:kDBFileName];
    NSError *error = nil;
    // path 为初始化传入的路径,判断路径下面是否存在数据库文件
    if (![[NSFileManager defaultManager] createDirectoryAtPath:path
    withIntermediateDirectories:YES
    attributes:nil
    error:&error]) {
    NSLog(@"init error:%@", error);
    }

    建表

    1
    2
    3
    4
    5
    6
    7
    create table if not exists t_Stuent (
    sid text,
    name text,
    insert_time integer,
    extended_data blob,
    primary key(sid)
    );

    插入

    1
    2
    3
    4
    5
    6
    7
    // 普通插入
    NSString *sql = @"INSERT INTO aTable(itemInfoId,userName,userId,cacheTime) VALUES (?1,?2,?3,?4)";
    // 插入或替换
    NSString *sql = @"INSERT OR REPLACE INTO aTable(itemInfoId,userName,userId,cacheTime) VALUES (?1,?2,?3,?4)";
    // 插入或忽略
    NSString *sql = @"INSERT OR IGNORE INTO aTable(itemInfoId,userName,userId,cacheTime) VALUES (?1,?2,?3,?4)";
    [db executeUpdate:sql, item.itemInfoId,item.userName, item.userId, [NSDate new]]

    查询

    1
    NSString *sql = @"SELECT * FROM aTable WHERE cacheTime < ? and itemInfoId = ? and workspaceItemInfoId is not null ORDER BY cacheTime DESC LIMIT 0,20;";

    更新

    1
    NSString *sql = @"UPDATE aTable SET cacheTime = ? WHERE itemInfoId = ?;"

    删除

    1
    2
    3
    [db executeUpdate:@"DELETE FROM aTable WHERE itemInfoId = ?;", item.itemInfoId];
    // 删除表
    @"DROP TABLE aTable";
  2. 连表查询

    1
    2
    3
    4
    5
    6
    7
    // 一般查询
    select * from aTable,bTable where aTable.id=aTable.id;
    // 内连接
    select a.name, b.name from aTable as a inner join bTable as b on a.id = b.id
    // 左连接
    select * from aTable left outer join bTable on aTable.id=bTable.id
    // 不支持右连接和全连接
  3. 索引
    sqlite索引的原理

    1
    2
    // 索引可以提高查询效率,但是生成索引需要更大的存储空间
    create index if not exists idxName on t_Stuent(name);
  4. 事务

    1
    2
    3
    4
    5
    6
    7
    FMDatabase *db;
    // 开始事务,内部执行sql语句 begin exclusive transaction
    [db beginTransaction];
    // 开始事务,内部执行sql语句 begin deferred transaction
    [db beginDeferredTransaction]
    // 提交,内部执行sql语句 commit transaction
    [db1 commit];

    两种开启事务的区别SQLite语法 BEGIN TRANSACTION

  5. 回滚

    1
    2
    3
    4
    5
    6
    7
    [[FMDatabaseQueue sharedInstance] inDeferredTransaction:^(FMDatabase *db, BOOL *rollback) {
    // 出错, 执行回滚操作
    // 内部执行 [self executeUpdate:@"rollback transaction"]
    if (error) {
    *rollback = YES;
    }
    }];
  6. 数据库语句缓存

    1
    2
    // 提高查询效率,实际使用字典进行缓存FMStatement
    [db setShouldCacheStatements:YES];

增加表字段,修改表名,修改数据库名称

增加表字段
ALTER TABLE aTable ADD COLUMN name TEXT
更改表名称
ALTER TABLE "aTable" RENAME TO "aTable_old_20170831";

表迁移数据

因为sqlite不支持直接修改某一列数据,可以将表A重命名为临时表B,然后,新建一个A表,将B表数据拷贝到A表中,然后删除临时表B即可

pragma扩展语句

PRAGMA语句是SQLITE数据的SQL扩展,是它独有的特性,主要用于修改SQLITE库或者内数据查询的操作。

SQLite中的PRAGMA语句攻略
pragma journal_mode = wal;
默认delete,开启wal模式之后,一般情况下写入性能更好.会生成两个文件:.shm和.wal
pragma synchronous = normal;
在sqlite3.0中默认为full,防止设备故障导致数据库损坏,但是读取性能差,off性能更好,但是对数据库保护不够,一般使用normal模式

加密

加密你的SQLite
我选择的是sqlcipher,FMDB也有加密的分支,可以通过CocoaPods安装

1
2
3
target 'MyApp' do
pod 'FMDB/SQLCipher'
end

初始化的时候调用db的setKey:就可以了

新的数据库方案

微信团队开源了一个数据库解决方案,叫做[WCDB](https://github.com/Tencent/wcdb),性能和安全性都通过博客看,非常不错,可以阅读他们的以下文章,进行了解学习
微信iOS SQLite源码优化实践
微信 SQLite 数据库修复实践
微信WCDB进化之路 - 开源与开始
微信移动端数据库组件WCDB系列(一)-iOS基础篇
微信移动端数据库组件WCDB系列(二) — 数据库修复三板斧
微信移动端数据库组件WCDB系列(三) — WINQ原理篇
微信移动数据库组件WCDB(四) — Android 特性篇
为什么要从FMDB迁移到WCDB?