iOS-OC 新手 数据库之FMDB 看这篇就够了(附Demo)
1. FMDB数据存储 - 概念篇
这个就是苹果自带的,可以操作数据库的包 image.png首先FMDB是对苹果sqlite的封装,sqlite是苹果自带的,FMDB给我们封装了很多好用的接口.那么数据库可以存储哪些类型数据呢,我们来一一解答
1.1 FMDB可以存储哪些类型数据
* INTEGER 整型
* TEXT 文本
* REAL 浮点型
* BLOB 二进制
对应到OC
里面就是
INTEGER ->int
,
TEXT -> NSString
,
REAL -> float
,
BLOB -> NSData
.
所以 如果我们要存储对象,或者图片的话,需要将其转换成NSData格式,
存储对象类型还需要进行必要的归档操作.
1.2 归档操作的步骤如下
1.需要实现这个协议 NSSecureCoding,
@interface MJPerson : NSObject <NSCoding,NSSecureCoding>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@end
2. 必须要实现这个方法,因为之前的归档,苹果认为是不安全的,会出现数据错乱的情况,所以修改了归解档的方法,
@implementation MJPerson
+ (BOOL)supportsSecureCoding{
return YES;
}
3. 再实现归解档
//归档的时候调用
//告诉编码器该如何归档
//将这个对象哪些属性编码起来
- (void)encodeWithCoder:(NSCoder *)encoder{//归档
[encoder encodeObject:self.name forKey:@"name"];
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(省略内容)
}
@end
上述是在模型操作,接下来是和NSData - MJPerson
的转换
归档: 转化为NSData----------------------------------------------------------------
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person
requiringSecureCoding:YES error:nil];
解档: 转化为MJPerson模型----------------------------------------------------------------
NSData *tmpData = [result objectForColumn:@"data"];//打印 "data"列
MJPerson *tmpPerson2 = [NSKeyedUnarchiver unarchivedObjectOfClass:
[MJPerson class] fromData:tmpData error:nil];
2. FMDB数据存储 - SQlite篇
在对数据库进行 增删改查 之前,必须要先 打开 数据库,操作完成之后,关闭数据库
2.1 创建一个数据库 - 以我的Demo工程为例
2.1.1首先创建一个从操作数据库的单例
@implementation GirlsDBTool
static FMDatabase *db_;
+ (instancetype)shareInstance{
static GirlsDBTool *mydb = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mydb = [[GirlsDBTool alloc]init];
});
//创建数据库
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"person.db"];
NSLog(@"path: %@",path);
db_ = [FMDatabase databaseWithPath:path];
return mydb;
}
- (FMDatabase *)db{
return db_;
}
@end
2.1.2 用数据库单例创建一张表(girls_table)
GirlsDBTool *girsDB = [GirlsDBTool shareInstance];
BOOL isOpen = [girsDB.db open];
if (isOpen) {
NSString *sql = @"create table if not exists girls_table
(id INTEGER primary key autoincrement,name TEXT not null ,
height REAL not null ,weight REAL not null ,
age INTEGER not null default 0,hobits TEXT not null,
birthPlace TEXT not null,photo BLOB)";
}
参数说明 - 所有的sql 语句 大小写都支持,不管你的数据类型 是TEXT
还是text
都可以
NSString *sql = @"
create table if not exists girls_table **如果不存在girls_table,则创建它
(id INTEGER primary key autoincrement, **主键 id,它会随着你数据递增
name TEXT not null , **创建name,数据类型为 字符串
height REAL not null , **创建height,浮点型
weight REAL not null ,
age INTEGER not null default 0, **创建age,整型
hobits TEXT not null,
birthPlace TEXT not null,
photo BLOB)"; **创建photo,NSData类型
2.1.3 将数据库语句 在这执行 每执行一条sql语句就会返回一个BOOL值,YES表示执行成功
BOOL isSuccess = [girsDB.db executeUpdate:sql];
如果成功,接下来就可以存数据了
BOOL isSaved = [girsDB.db executeUpdateWithFormat:
@"insert into girls_table(name,height,weight, age,hobits, birthPlace, photo)
values(%@,%f,%f,%d,%@,%@,%@)", value0,value1.floatValue,value2.floatValue,
value3.intValue,value4,value5,value6];
完成操作后关闭数据库
if ([girsDB.db close]) {
NSLog(@"关闭数据库");
}
小结:上述步骤就是如下几点
1.获取数据库单例,打开数据库, BOOL isOpen = [girsDB.db open];
- 执行sql语句 ,先建表,
- 存储你需要存储的数据,
4.关闭数据库,
我这里使用了数据库可视化软件 Navicat Premium
可以查看数据库变更容易,里面数据库的地址就是单例里面的那个路径(NSTemporaryDirectory()
),每次操作完之后,快捷键command + R 刷新数据库
3. FMDB API的一些说明
除开查询(query
),其他的操作都可以认为是更新操作,修改-删除-新增都是(update
)
FMDatabase
操作的数据库表,
FMResultSet
查询返回的结果集
FMDatabaseQueue
多线程操作数据库
查询
查询语句执行之后返回一个结果集FMResultSet
,然后你在while循环里取你要的参数,为什么要搞一个while循环??? 因为API就是这个设计的,
打开数据库
[self.db open];
/**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型*/
[self.db executeQuery:@"select * from t_table"];
/**此种方式后面拼接的参数可以为int double等基本数据类型 因为是使用的占位符*/
[self.db executeQueryWithFormat:@"SELECT name, age, score from t_table where name = %@", @"Jake"];
/**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型 将对象依次防近视数组*/
FMResultSet *result = [self.db executeQuery:@"select *from t_table where age > ?" withArgumentsInArray:@[@12]];
while (result.next) {
这里按照你的需求取值,取某个特定的名字,身高,某种数据类型,某一列.....
NSLog(@"从数据库查询成功");
}
FMResultSet根据column name获取对应数据的方法
intForColumn:
longForColumn:
longLongIntForColumn:
boolForColumn:
doubleForColumn:
stringForColumn:
dataForColumn:
dataNoCopyForColumn:
UTF8StringForColumnIndex:
objectForColumn:
修改
[self.db open];
0.直接sql语句
BOOL result = [db executeUpdate:@"update 'yp_table' set ID = 110 where name = 'x1'"];
1.
BOOL result = [db executeUpdate:@"update 'yp_table' set ID = ? where name = ?",@111,@"x2" ];
2.
BOOL result = [db executeUpdateWithFormat:@"update 'yp_table' set ID = %d where name = %@",113,@"x3" ];
3.
BOOL result = [self.db executeUpdate:@"update 'yp_table' set ID = ? where name = ?" withArgumentsInArray:@[@113,@"x3"]];
if (result) {
NSLog(@"update 'yp_table' success");
} else {
NSLog(@"insert into 't_studet' fail");
}
[self.db close];
插入
[self.db open];
此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型
[self.db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
/**此种方式后面拼接的参数可以为int double等基本数据类型 因为是使用的占位符*/
[self.db executeUpdateWithFormat:@"insert into t_table(name, age, score, data) values(%@, %d , %f, %@)", @"jake", 12, 91.0, [NSData data]];
/**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型 将对象依次放进数组*/
[self.db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)" withArgumentsInArray:@[@12, @91.0, [NSData data]]];
BOOL result = [self.db executeUpdate:@"insert into 'yp_table'(ID,name,phone,score) values(?,?,?,?)" withArgumentsInArray:@[@113,@"x3",@"13",@53]];
if (result) {
NSLog(@"insert into 't_studet' success");
} else {
NSLog(@"insert into 't_studet' fail");
}
[self.db close];
删除
[self.db open];
0.直接sql语句
BOOL result = [db executeUpdate:@"delete from 'yp_table' where ID = 110"];
1.
BOOL result = [db executeUpdate:@"delete from 'yp_table' where ID = ?",@(111)];
2.
BOOL result = [db executeUpdateWithFormat:@"delete from 'yp_table' where ID = %d",112];
3.
BOOL result = [self.db executeUpdate:@"delete from 'yp_table' where ID = ?" withArgumentsInArray:@[@113]];
if (result) {
NSLog(@"delete from 'yp_table' success");
} else {
NSLog(@"insert into 't_studet' fail");
}
[self.db close];
这个是运行的demo-包含增删改查-没有模拟多线程的情况
如果有错误-表达不够清晰的地方,评论区留言 - let me know