摘要:关键点:创建、插入、查询、数据格式化
第三方框架FMDB
------------------------------------------------------------------------------------------------------------
开源
1)什么是FMDB 
FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API。
2)FMDB的优点 
a、使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码 
b、对比苹果自带的Core Data框架,更加轻量级和灵活

c、提供了多线程安全的数据库操作方法,有效地防止数据混乱
---------------------------------------------------------------------------------
最主要的类
FMDatabase:对象代表数据库,主要功能执行SQL语句
FMResultSet:对象代表查询结果,主要用于保存和处理select语句的查询结果,主要用于保存和处理SELECT语句的查询结果
注意:
1、FMDB将所有建表、插入、更新、删除的操作都叫Update,执行这些SQL语句的方法都是
executeUpdate、executeUpdateWithFormat:
 
 
2、查询:
只有执行SELECT语句的方法叫executeQuery:
    给SQL语句传参数:
     ?  :都是对象,表示为其他参数,NSString,NSArray, NSDictionary,或va_list等
     Format:支持各种基本数据类型
处理查询结果FMResultSet:用于存储executeQuery查询出来的结果
     数据集 next:一次取一次记录
               每条记录独有几个字段,取字段XXXForColumn,XXX代表字段的类型
FMResultSet  提供了很多方法来获得所需的格式的值:
    intForColumn:
    longForColumn:
    longLongIntForColumn:
    boolForColumn:
    doubleForColumn:
    stringForColumn:
    dataForColumn:
    dataNoCopyForColumn:
    UTF8StringForColumnIndex:
    objectForColumn:
这些方法也都包括 {type}ForColumnIndex 的这样子的方法,参数是查询结果集的列的索引位置。
你无需调用  [FMResultSet close]来关闭结果集, 当新的结果集产生,或者其数据库关闭时,会自动关闭。
 
数据格式化
支持的格式:
 
自动识别对象:?
字符串:%@, %c, %s
数值:%d, %D,%i,%u,%U,%ld, %lu,%lld, %llu ,%f
%hi, %hu, %qi, %qu,
%g
 
你需要在SQL语句中使用 % 字符,你应该使用 %%
 
除此之外的修饰符可能导致无法预知的结果
 
executeUpdate:?,SQLite风格
execute*WithFormat: 这是NSString风格的参数
 
使用FMDB,插入数据前,你不要花时间审查你的数据。你可以使用标准的SQLite数据绑定语法。
INSERT INTO myTable VALUES (?, ?, ?)
SQLite会识别 “?” 为一个输入的点位符, 这样的执行会接受一个可变参数(或者表示为其他参数,如NSArray, NSDictionary,或va_list等),会正确为您转义。
你也可以选择使用命名参数语法。
INSERT INTO myTable VALUES (:id, :name, :value)
参数名必须以冒名开头。SQLite本身支持其他字符,当Dictionary key的内部实现是冒号开头。注意你的NSDictionary key不要包含冒号。
NSDictionary *argsDict = [NSDictionary dictionaryWithObjectsAndKeys:@"My Name", @"name", nil];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];
而且,代码不能这么写(为什么?想想吧。答:因为字典提供的参数值不够)
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has \" lots of ' bizarre \" quotes '"];
你应该:
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has " lots of ' bizarre " quotes '"];
 
 提供给 -executeUpdate: 方法的参数都必须是对象
就像以下的代码就无法工作,且会产生崩溃。
 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];
 正确有做法是把数字打包成 NSNumber对象
 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];
 或者,你可以使用  -execute*WithFormat: ,这是NSString风格的参数
 [db executeUpdateWithFormat:@"INSERT INTO myTable VALUES (%d)", 42];
 -execute*WithFormat:  的方法的内部实现会帮你封装数据, 以下这些修饰符都可以使用: %@, %c, %s, %d, %D,%i, %u, %U, %hi, %hu, %qi, %qu, %f, %g, %ld, %lu, %lld, and %llu.  除此之外的修饰符可能导致无法预知的结果。 一些情况下,你需要在SQL语句中使用 % 字符,你应该使用 %%。
 
//————————————-------------------—create—创建表------------------------------------------
@property (strong, nonatomic)FMDatabase *fmdb;
NSString *dbFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject]stringByAppendingPathComponent:@"demo3.db"];
//此对象代表数据库
self.fmdb = [FMDatabase databaseWithPath:dbFilePath];
//1. 打开数据库
if([self.fmdb open]){
    //2. 执行建表SQL
    BOOL res = [self.fmdb executeUpdate:@"CREATE TABLE IF NOT EXISTS emp(id integer PRIMARY KEY, name varchar(20) NOT NULL, age integer, salary double)"];
    if(res){
        NSLog(@"建表成功");
    }else{
        NSLog(@"建表失败:%@", [self.fmdb lastError]);
    }
}
[self.fmdb close];
//—————————------------—————insert into-插入数据------------------------------------------
1、插入数据:executeUpdateWithFormat
[self.fmdb open];
BOOL res = [self.fmdb executeUpdateWithFormat:@"INSERT INTO emp (name, age, salary) VALUES (%@, %d, %f)", self.nameTF.text, self.ageTF.text.intValue, self.salaryTF.text.doubleValue];
if(!res){
    NSLog(@"插入数据失败:%@", [self.fmdb lastError]);
}
flage=[self.fmDb executeUpdateWithFormat:@"insert into myRecord(pID,timer) values(%d,%@)",self.Mypoem.poemID,currentTime];
 
2、用问号代替字段,拼接方式:executeUpdate
NSString * sql = @"insert into user (name, password) values(?, ?) ";
NSString * name = [NSString stringWithFormat:@"queue111 %d", i];
BOOL res = [db executeUpdate:sql, name, @"boy"];
if (!res) {
    debugLog(@"error to add db data: %@", name);
} else {
    debugLog(@"succ to add db data: %@", name);
}
//----------------------------delete-删除数据------------------------------------------
删除某条语句
BOOL flag = [self.fmdb executeUpdate:@"DELETE FROM test_tab WHERE name=?",@"jiajia"];
 
删除表
BOOL flag = [self.fmdb executeUpdate:@"DELETE FROM test_tab];
//----------------------------update-修改数据------------------------------------------
修改数据:
格式:update 表名 SET 修改内容 where 条件
update foods SET id = 800 - id
 
//----------------------------select-查询数据------------------------------------------
1、查询指定数据:executeQueryWithFormat
[self.fmDb open];
NSLog(@"%d",_Mypoem.poemID);
FMResultSet *poemRSet=[self.fmDb executeQueryWithFormat:@"select D_SHI,D_INTROSHI from T_SHI where D_ID = %d",self.Mypoem.poemID];
while ([poemRSet next]) {
    NSString *temp1=[poemRSet stringForColumn:D_SHI];
    NSString *temp2=[poemRSet stringForColumn:D_INTROSHI];
    self.textView.text=[temp1 stringByAppendingString:temp2];
    NSLog(@"%@",[temp1 stringByAppendingString:temp2]);
}
[self.fmDb close];
 
2、查询个数:(只会返回一个值):executeQuery
1)select count(*) allrecord from myRecord   //allrecord:给字段的取别名
 
2)查询指定的个数:executeQueryWithFormat
FMResultSet *resultSet=[self.fmDb executeQueryWithFormat:@"select count(pID) allCollection from myCollection where pID = %d",self.Mypoem.poemID];
NSLog(@"self.Mypoem.poemID = %d",self.Mypoem.poemID);
[resultSet next];
int count=[resultSet intForColumn:@"allCollection"];
NSLog(@"判断是否已经存在了这条记录:%d",count);
 
3、
sql = @"INSERT INTO USER (name,phone,idcode) VALUES (?,?,?) ";
BOOL res = [db executeUpdate:sql,nameTextField.text,phoneTextField.text,IDTextField.text];
if (!res) {
    NSLog(@"error to insert data");
    mes = @"数据插入错误";
}else{
    NSLog(@"insert succeed");
    mes = @"数据插入成功";
}
4、
FMResultSet *resultSet = [self.fmdb executeQuery:@"SELECT * FROM emp WHERE id > ?", @2];
while([resultSet next]){//取一条记录
    //取这条记录中的每个字段值
    int ID = [resultSet intForColumn:@"id"];
    NSString *name = [resultSet stringForColumn:@"name"];
    int age = [resultSet intForColumn:@"age"];
    double salary = [resultSet doubleForColumn:@"salary"];
    self.displayLabel.text = [self.displayLabel.text stringByAppendingFormat:@"\n%d,%@,%d,%.2lf", ID, name, age, salary];
}
[self.fmdb close];
 
 
 
//—————-----------------———补充:多表关联 ---------------------------------
//———————方式一:
1、支持多表连接,例如
select * from student,class where student.cid=class.id;
select table1.abc from table1,table2 where table1.xxx=table2.xxx;
例子:
关于sqlite 多表查询的,有3个表
A表
    id user
    1  admin
    2  guest
B表
    id app_name version
    1  app_1    1.1
    2  app_2    1.3
    3  app_3    1.4
C表
    id user_id app_name_id
    1  1      1
    2  2      2
    3  1      3
要求:通过SELECT把A表中admin使用的app的app_name和version显示出来 
SQL语句:
select A.user,B.app_name,B.version from A,B,C where A.user='admin' and A.id=C.user_id and C.app_name_id=B.id
//———————方式二:
2、 inner join table on 
记录一下sqlite中多表查询。
表1:品牌:brands( brandid vARCHAR(20),
             brand VARCHAR(20),
             remark vARCHAR(100))
表2:类型:types( typeid vARCHAR(20),
            type VARCHAR(20),
            remark vARCHAR(100))
表3:品牌:levels( levelid vARCHAR(20),
             level VARCHAR(20),
             remark vARCHAR(100))
表4:油品:oils( oilid vARCHAR(20),brandid VARCHAR(20),typeid vARCHAR(20),levelid vARCHAR(20),remark vARCHAR(100))
说明一下:前三个表为基本信息,即油品的品牌、类型、级别,表4为油品信息,那么该如何显示油品的基本信息呢?
select brands.brand,types.type,levels.level from oils
inner join brands on oils.brandid = brands.brandid
inner join types on oils.typeid =types.typeid
inner join levels on oils.levelid =levels.levelid
 
再如:
select table1.abc from table1 inner join table2 on table1.xxx=table2.xxx;
 
//———————方式三:
3、支持左外连接(left outer join)
例如:
select * from foods
left outer join food_types
on foods.id=food_types.food_id
4、不支持右外连接和全连接。
//  唐诗三百
[self.fmdb open];
NSString *sql=nil;
if ([self.myType isEqualToString:@"myCollection"]==YES) {
//我的收藏
要特别注意:是对哪些表进行操作的
    sql=@"select T_SHI.D_AUTHOR,T_SHI.D_KIND,T_SHI.D_TITLE,T_SHI.D_ID,myCollection.timer from T_SHI,myCollection where T_SHI.D_ID = myCollection.pID";
}else{
//我的记录
    sql=@"select T_SHI.D_AUTHOR,T_SHI.D_KIND,T_SHI.D_TITLE,T_SHI.D_ID,myRecord.timer from T_SHI,myRecord where T_SHI.D_ID = myRecord.pID";
}
NSLog(@"SQL = %@",sql);
FMResultSet *poemRSet=[self.fmdb executeQuery:sql];
//    NSLog(@"错误:%@",[self.fmdb lastError]);
while ([poemRSet next]) {
    Poem *newPoem=[[Poem alloc]init];
    newPoem.poemAuthor=[poemRSet stringForColumn:D_AUTHOR];
    newPoem.poemKind=[poemRSet stringForColumn:D_KIND];
    newPoem.poemTime=[poemRSet stringForColumn:TIMER];
    newPoem.poemTitle=[poemRSet stringForColumn:D_TITLE];
    newPoem.poemID=[poemRSet intForColumn:D_ID];
    NSLog(@"%@",[newPoem description]);
    [self.allPoemInfo addObject:newPoem];
}
[self.fmdb close];
//------------------------------------End---------------------------------------------
fmdb-master.zip
101.2 KB

摘要:FMDatabaseQueue、事务处理
FMDatabaseQueue 及线程安全
在多个线程中同时使用一个FMDatabase实例是不明智的。现在你可以为每个线程创建一个FMDatabase对象。 不要让多个线程分享同一个实例,它无法在多个线程中同时使用。 若此,坏事会经常发生,程序会时不时崩溃,或者报告异常,或者陨石会从天空中掉下来砸到你Mac Pro.  总之很崩溃。所以,不要初始化FMDatabase对象,然后在多个线程中使用。请使用 FMDatabaseQueue,它是你的朋友而且会帮助你。以下是使用方法:
首先创建队列。
//-----------------------------队列FMDatabaseQueue------------------------------------------
使用队列FMDatabaseQueue
     在多线程环境下,为了防止同时执行SQL语句时发生冲突,可以考虑使用FMDatabaseQueue来执行SQL语句。
在inDatabase:^(FMDatabase *db){在这里执行SQL语句},操作过程都是相同的
 
NSString *dbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject]stringByAppendingPathComponent:@"demo4.db"];
self.dbPath = dbPath;
//相当于一个FMDatabase对象
self.queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
1)创建表
[self.queue inDatabase:^(FMDatabase *db) {
    BOOL res = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS person(id integer PRIMARY KEY, name text NOT NULL)"];
    if(res){
        NSLog(@"建表成功");
    }else{
        NSLog(@"建表失败");
    }
}];
2)插入值
[self.queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO person(name) VALUES(?)", @"Daniel"];
}];
 
3)查询:
[self.queue inDatabase:^(FMDatabase *db) {
    FMResultSet *resultSet = [db executeQuery:@"SELECT * FROM person"];
    while ([resultSet next]) {
        int ID = [resultSet intForColumn:@"id"];
        NSString *name = [resultSet stringForColumn:@"name"];
        NSLog(@"ID:%d,name:%@", ID, name);
    }
}];
 
//一段查询数据库的代码
NSString *dbPath=[[NSBundle mainBundle]pathForResource:@"poem" ofType:@"db"];
if (dbPath == nil) {
    NSLog(@"没有找到数据库!");
}
NSLog(@"dbpath = %@",dbPath);
FMDatabase *fmdb=[FMDatabase databaseWithPath:dbPath];//获取数据库
[fmdb open];//打开数据库
NSLog(@"%d",_Mypoem.poemID);
FMResultSet *poemRSet=[fmdb executeQueryWithFormat:@"select D_SHI,D_INTROSHI from T_SHI where D_ID = %d",self.Mypoem.poemID];//条件查询:where D_ID == self.Mypoem.poemID 的记录,记得需要使用格式化的语句:executeQueryWithFormat
while ([poemRSet next]) {//获取一条语句[poemRSet next]的返回值是BOOL类型的
    NSString *temp1=[poemRSet stringForColumn:D_SHI];//读取字段为D_SHI下的内容
    NSString *temp2=[poemRSet stringForColumn:D_INTROSHI];//读取字段为D_INTROSHI下的内容
    self.textView.text=[temp1 stringByAppendingString:temp2];//拼接后,赋值给self.textView.text
    NSLog(@"%@",[temp1 stringByAppendingString:temp2]);
}
[fmdb close];//有打开,就要有关闭
//--------------------------------------------------------------------------------
事务处理(Transaction)
FMDatabase *db = [FMDatabase databaseWithPath:self.dbPath];
[db open];
//开始一个事务
[db beginTransaction];
[db executeUpdate:@"INSERT INTO person(name) VALUES(?)", @"Shasha"];
//如果在执行某条SQL语句时出现问题,由于我们处在一个事务中,所以执行成功的SQL会自动回滚(恢复以前的数据)
//[db rollback];//主动回滚
 [db executeUpdate:@"INSERT INTO person(name) VALUES(?)", @"Shanshan"];
//提交一个事务
[db commit];
//在队列中执行事务
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO person(name) VALUES(?)", @"AAA"];
    [db executeUpdate:@"INSERT INTO person(name) VALUES(?)", @"BBB"];
    //*rollback = YES;//主动回滚
}];

第三方框架FMDB的更多相关文章

  1. iOS-数据持久化-第三方框架FMDB的使用

    FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了 ...

  2. [iOS]数据库第三方框架FMDB详细讲解

    [iOS]数据库第三方框架FMDB详细讲解 初识FMDB iOS中原生的SQLite API在进行数据存储的时候,需要使用C语言中的函数,操作比较麻烦.于是,就出现了一系列将SQLite API进行封 ...

  3. 第三方框架----FMDB的使用

    以下是SQLite API进行封装的库FMDB的简单使用 : FMDB框架的下载地址 :https://github.com/ccgus/fmdb 代码如下 : ////  ViewControlle ...

  4. SQLite数据库框架--FMDB简单介绍

    1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码 对比 ...

  5. FMDB第三方框架

    FMDB是同AFN,SDWebImage同样好用的第三方框架,它以OC的方式封装了SQLite的C语言API,使得开发变得简单方便. 附上github链接https://github.com/ccgu ...

  6. 第三方库FMDB的使用

    1.FMDB简介 什么是FMDB FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API. 为什么使用FMDB 使用起来更加面向对象,省去了很多麻烦.冗余的 ...

  7. iOS开发--SQLite重要框架FMDB的使用

    什么是FMDB: FMDB是一个和iOS的SQLite数据库操作相关的第三方框架.主要把C语言操作数据库的代码用OC进行了封装.使用者只需调用该框架的API就能用来创建并连接数据库,创建表,查询等. ...

  8. iOS技术面试07:第三方框架

    1ios框架分为:cocoa Touch:UIKit.Foundation.附属框架 Media:OpenGL ES.EAGL.Quartz.Core Animation.Core Audio.    ...

  9. iOS-常用的第三方框架的介绍

    写iOS 程序的时候往往需要很多第三方框架的支持,可以大大减少工作量,讲重点放在软件本身的逻辑实现上. GitHub 里面有大量优秀的第三方框架,而且 License 对商业很友好.一下摘录一下几乎每 ...

随机推荐

  1. Hadoop中FileSystem的append方法

    今天在使用Hadoop 1.1.2版本进行FileSystem的append操作时报以下异常: org.apache.hadoop.ipc.RemoteException: java.io.IOExc ...

  2. .NET中获取字符串的MD5码

    C# 代码: 导入命名空间(需要在Web页面的代码页中引用) using System.Web.Security; 获取MD5码 string Password = FormsAuthenticati ...

  3. dedecms

    http://www.duodede.com/free/  [free templte] http://www.xiuzhanwang.net/d

  4. C++11 能好怎?

    0. 摘要 近期读了一些关于C++11标准的材料. 本篇博客将从新标准的优点.与旧版本的区别和使用方法三个角度,大致介绍我对C++11的认识. C++11标准,原名C++0x, 是03版旧标准的更新. ...

  5. Shell中的变量

    一.什么是变量 变量在 bash 环境中是非常重要的,简单的说,就是让某一个特定字符串来代表不固定的内容.举例: 那就是:『 y = ax + b 』这东西,在等号左边的(y)就是变量,在等号右边的( ...

  6. LINUX如何查看其他用户的操作

    我们知道可以使用history命令,查看自己的操作记录,但如果你是root用户,如何查看其它用户的操作记录呢?   其实history命令只是把当前用户目录下的~/.bash_History文件内容列 ...

  7. 模板引擎doT.js介绍及如何判断对象为空、如何嵌套循环···

    doT.js 灵感来源于搜寻基于 V8 和 Node.js ,强调性能,最快速最简洁的 JavaScript 模板函数 引入 javascript 文件: <script type=" ...

  8. Linux学习笔记----(2)

    闲着无事,就敲起了Linux 命令,熟悉一下.记得昨天在书上看到了 find命令的用法,觉得挺神奇的. 其中 find 能够确定文件的查找深度 于是 敲了如下命令: #mkdir father #to ...

  9. PL/pgSQL的RETURN QUERY例子

    我的例子: 数据准备: create table custinfo(custid integer,callingcnt integer); ,),(,),(,); 函数生成: CREATE OR RE ...

  10. 在Linux(Ubuntu/openSUSE/CentOS)下配置ASP.NET(Apache + Mono)转载+补充

    错误:Network error: Connection refused 解决办法: 执行 $sudo apt-get install openssh-server 安装ssh协议 执行ifconfi ...