iOS Sqlite和FMDB的使用、详解(附Demo)

sqlitedata.png

一.SQLite简介
先莫急,认真看完简介,一定对你有帮助的(已经熟知的跳过简介,当你在公司有同事不会sqlite的时候,你就可以先简单的说几句SQLite的简介以达到装逼的目的,装b效果如果100分的话,大多基本上会给你90分了)。
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。

二.sqlite使用之创建数据库,创建表,对表内数据操作等

1.创建数据库(前面的准备工作(导入libsqlite3库)就不介绍了)

- (void)createDataBase{
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentsStr = [paths objectAtIndex:0];
  //应用的文档目录
  NSLog(@"%@",documentsStr);
  NSString *database_path = [documentsStr stringByAppendingPathComponent:KDBName];
  //打开数据库,如果没有的话,就会在该目录创建该数据库。
  if(sqlite3_open([database_path UTF8String], &db) != SQLITE_OK) {
      sqlite3_close(db);
  }
}

2.创建表

 - (void)createTable{
  //IF NOT EXISTS 如果不存在 (如果该数据库已经存在了该表,则sqlite3_exec在执行数据库操作的时候不会报错给我们,如果表已经存在了,又没有加这个判断的话,会执行不成功并关闭数据库)
  NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (ID INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, sex INTEGER, phoneNum VARCHAR);",KTBUserInfo];
  [self execSql:sql];
  /*
   * sqlite数据库里面的数据类型参考SQLite数据库的文档,这里的sql语句CREATE、INTEGER等关键词,大写是为了区分这是系统的,并不是规定的,小写也是能正常通过的,不过,为了规范,建议大写。
   */
}

3.插入数据

- (void)insertData{
  NSString *sql = [NSString stringWithFormat:
                  @"INSERT INTO '%@' ('name', 'age', 'sex', 'phoneNum') VALUES ('%@', '%@', '%@','%@');",KTBUserInfo, @"张三", @"23", @"1",@"18875022022"];
  [self execSql:sql];

  sql = [NSString stringWithFormat:
       @"INSERT INTO '%@' ('name', 'age', 'sex', 'phoneNum') VALUES ('%@', '%@', '%@','%@');",KTBUserInfo, @"李四", @"24", @"0",@"18875022023"];
  [self execSql:sql];

  sql = [NSString stringWithFormat:
       @"INSERT INTO '%@' ('name', 'age', 'sex', 'phoneNum') VALUES ('%@', '%@', '%@','%@');",KTBUserInfo, @"王五", @"25", @"1",@"18875022024"];
  [self execSql:sql];
}

execSql方法

- (void)execSql:(NSString *)sql{
  char *err;
  sqlite3_open([[documents stringByAppendingPathComponent:KDBName] UTF8String], &db);
  sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err);
  sqlite3_close(db);
 }

就不贴修改、删除数据的代码了,附件demo里有详细代码。只要sql不是SELECT命令的都视为更新操作(使用exec开头的方法)。就包括 CREAT,UPDATE,INSERT,ALTER,BEGIN,COMMIT,DETACH,DELETE,DROP,END,EXPLAIN,VACUUM,REPLACE等等。SELECT命令的话,使用sqlite3_prepare开头的方法。

4.查询数据

- (void)queryDataWithTableName:(NSString *)tbName{
  sqlite3_open([[documents stringByAppendingPathComponent:KDBName] UTF8String], &db);

  NSString *sqlQuery = [NSString stringWithFormat:@"SELECT * FROM %@;",tbName];

  sqlite3_stmt *statement;
  if (sqlite3_prepare_v2(db, [sqlQuery UTF8String], -1, &statement, nil) == SQLITE_OK) {
      while (sqlite3_step(statement) == SQLITE_ROW) {
        
          char *name = (char*)sqlite3_column_text(statement, 1);
          NSString *nsNameStr = [[NSString alloc] initWithUTF8String:name];
        
          int age = sqlite3_column_int(statement, 2);
          int sex = sqlite3_column_int(statement, 3);
        
          int columnCount = sqlite3_column_count(statement);
          if (columnCount == 5) {//为了兼容我这里两个表,其中一个表少一个字段,拣个懒
              char *phoneNum = (char*)sqlite3_column_text(statement, 4);
              NSString *phoneNumStr = [[NSString alloc] initWithUTF8String:phoneNum];                
              NSLog(@"%@: name:%@ age:%d sex:%d phoneNum:%@",tbName,nsNameStr,age,sex,phoneNumStr);
          }else{
              NSLog(@"%@: name:%@ age:%d sex:%d",tbName,nsNameStr,age,sex);
          }
      }
  }else{
      NSLog(@"%@查询数据失败",tbName);
  }
  sqlite3_close(db);
}

三.FMDB的用法

由于原生的SQLite在进行数据操作的时候,使用的是C语言中的函数,对于我这种C语言又是小白的人,就会感觉比较麻烦。程序员都是懒人,于是,出了一系列的对SQLite的API进行封装的库,如FMDB。还有一些其他的,就不列举了,自行百度。
1.FMDB简介
<a href='https://github.com/ccgus/fmdb'>FMDB</a>是针对iOS的libsqlite3框架的封装的一个简易库(简单易学,轻量级,使用灵活),它用起来和SQLite类似,而且,对多线程并发操作进行了处理,所以线程安全。
2.比较重要的几个类
FMDB.h 引入了你在使用FMDB过程中可能会用到的几个类。
FMDatabase 代表一个单独的SQLite数据库,用它调用方法执行sql语句,类似原生sqlite3。
FMResultSet 在使用FMDatabase执行了查询的sql语句后,得到的结果集,就是FMResultSet。
FMDatabaseQueue 多线程中,执行数据操作,查询等。

3.使用FMDB创建数据库和表(首先实现文件里声明全局变量fmdb)

@interface ViewController (){
  sqlite3 *db;
  FMDatabase *fmdb;//!< FMDatabase,执行数据操作,查询。
}
@end
@implementation ViewController
#pragma amrk - fmdb创建数据库
- (void)fmdbCreate{
  NSString *database_path = [documents stringByAppendingPathComponent:KFMDBName];
  //数据库打开、创建
  fmdb = [FMDatabase databaseWithPath:database_path];
}
#pragma amrk - fmdb创建表
- (void)fmdbTableCreate{
  NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (ID INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, sex INTEGER, phoneNum VARCHAR);",KTBUserInfo];
  [self fmdbExecSql:sql];
}
#pragma mark - fmdbUpdate
- (void)fmdbExecSql:(NSString *)sql{
  if ([fmdb open]) {
    
      /*
       * 只要sql不是SELECT命令的都视为更新操作(使用executeUpdate方法)。就包括 CREAT,UPDATE,INSERT,ALTER,BEGIN,COMMIT,DETACH,DELETE,DROP,END,EXPLAIN,VACUUM,REPLACE等等。SELECT命令的话,使用executeQuery方法。
       * 执行更新返回一个BOOL值。YES表示 执行成功,否则表示有错误。你可以调用 -lastErrorMessage 和 -lastErrorCode方法来得到更多信息。
       */
      if ([fmdb executeUpdate:sql]) {
          NSLog(@"%@%@%@",@"fmdb操作表",KTBUserInfo,@"成功!");
      }else{
          NSLog(@"%@%@%@ lastErrorMessage:%@,lastErrorCode:%d",@"fmdb创建",KTBUserInfo,@"失败!",fmdb.lastErrorMessage,fmdb.lastErrorCode);
      }
  }else{
      NSLog(@"%@",@"fmdb数据库打开失败!");
  }
}    
@end

同样的道理,只有是操作数据的命令,都是调用executeUpdate方法,查询命令SELECT则调用executeQuery开头的方法。这里就不列举增删改的方法了。

4.fmdb查询数据

- (void)fmdbSelectData{
  NSString *sqlQuery = [NSString stringWithFormat:@"SELECT * FROM %@;",KTBUserInfo];

  //根据条件查询,如果成功返回FMResultSet对象,错误返回nil。与执行更新相当,支持使用NSError参数。
  FMResultSet *resultSet = [fmdb executeQuery:sqlQuery];

  //遍历结果集合

  while ([resultSet  next]){
      NSString *name = [resultSet
                      objectForColumnName:@"name"];
      int age = [resultSet intForColumn:@"age"];
      int sex = [resultSet intForColumn:@"sex"];
      NSString *phone = [resultSet objectForColumnName:@"phoneNum"];
        
      NSLog(@"%@: name:%@ age:%d sex:%d phoneNum:%@",KTBUserInfo,name,age,sex,phone);
  }
  /*
   * fmdb封装过后的读取数据是要比原生的sqlite3方便了很多哈
   */
}

5.fmdb多线程

- (void)fmdbQueue{
  //创建队列
  FMDatabaseQueue *queue = [FMDatabaseQueue
                          databaseQueueWithPath:[documents stringByAppendingPathComponent:KFMDBName]];
  __block BOOL tag = true;
  //把任务放到到队列里
  [queue inTransaction:^(FMDatabase *dbe, BOOL *rollback)
   {
       tag &= [dbe executeUpdate:@"INSERT INTO userInfo ('age') VALUES (?)",[NSNumber numberWithInt:11]];
       tag &= [dbe executeUpdate:@"INSERT INTO userInfo ('age') VALUES (?)",[NSNumber numberWithInt:22]];
       tag &= [dbe executeUpdate:@"INSERT INTO userInfo ('age') VALUES (?)",[NSNumber numberWithInt:33]];
       //如果有错误 回滚
       if (!tag){ 
           *rollback = YES;
           return;
       }
   }];
}

6.查询结果获取数据格式的方法,在FMResultSet.h文件里面,搜索包含ForColumn的方法定义。然后,你就会发现类似这种doubleForColumn、doubleForColumnIndex的方法,注释也是写的非常的详细,不懂英语其实翻译一下就搞定,机智如我。

四.工具推荐
喜欢用客户端的自行百度搜索SQLiteManager for mac 破解版,毕竟找工具还是自力更生。我不喜欢客户端,有没有简单粗暴的直接可以打开的?有!如果你有装火狐浏览器、就应该会用插件。不会的也可以下一个火狐浏览器,开发用还是很ok的。

tmp2e0f5d0a.png

<a href='https://pan.baidu.com/s/1nvwFCST'>点击跳转源码下载地址</a>

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

推荐阅读更多精彩内容