iOS FMDB資料庫框架使用 —— HERO部落格
FMDB簡介:
是iOS平臺的第三方資料庫框架,將SQLite API以OC的方式進行封裝,面向物件,使用便捷。
主要的類:
FMDatabase:一個FMDatabase物件就代表一個單獨的SQLite資料庫,用來執行SQL語句,進行增刪查改操作。
FMResultSet:使用FMDatabase執行查詢後的結果集。
FMDatabaseQueue:保證執行緒安全,可以在多執行緒中同時讀寫、執行多個查詢或更新。
使用:
建立佇列物件:
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"HWDownloadVideoCaches.sqlite"]; // 建立佇列物件,內部會自動建立一個數據庫, 並且自動開啟 _dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
創表:下面代表建立一張名為t_videoCaches的資料表,包含3個欄位,預設且自增的主鍵id欄位、totalFileSize欄位、url欄位。如“url text”代表欄位名字是url,型別是text,其中除主鍵外,型別可以不寫,為了方便閱讀及程式設計規範還是建議寫上。
[_dbQueue inDatabase:^(FMDatabase *db) { // 創表 BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_videoCaches (id integer PRIMARY KEY AUTOINCREMENT, totalFileSize integer, url text)"]; if (result) { NSLog(@"建立成功"); }else { NSLog(@"建立失敗"); } }];
常用型別:
整數資料型別:integer、bigint、smallint、tinyint
浮點資料型別:float、double、real
字元型資料型別:char(n)、varchar(n)、text
二進位制資料:blob
日期型別:date、time、datetime、timestamp
增加資料:這裡有一點要注意,不要直接傳入基礎型別,如int,要封裝成物件,不然會crash掉。
[_dbQueue inDatabase:^(FMDatabase *db) { BOOL result = [db executeUpdate:@"INSERT INTO t_videoCaches (totalFileSize, url) VALUES (?, ?)", [NSNumber numberWithInteger:1000], @"https://blog.csdn.net/hero_wqb"]; if (result) { NSLog(@"插入成功"); }else { NSLog(@"插入失敗"); } }];
刪除資料:下面代表通過url在t_videoCaches表中查詢資料,並將其刪除。
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"DELETE FROM t_videoCaches WHERE url = ?", url];
if (result) {
NSLog(@"刪除成功");
}else {
NSLog(@"刪除失敗");
}
}];
查詢資料:
1)快速查詢某一資料:下面代表在t_videoCaches表中,根據url查詢資料對應的totalFileSize。對應有stringForColumn:、boolForColumn:、doubleForColumn:、dataForColumn:、objectForColumn:等方法。
NSInteger totalFileSize = [db intForQuery:@"SELECT totalFileSize FROM t_videoCaches WHERE url = ?", url];
2)根據查詢條件,返回一個集合:下面代表查詢所有資料。
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches"];
while ([resultSet next]) {
NSInteger totalFileSize = [resultSet intForColumn:@"totalFileSize"];
NSString *url = [resultSet stringForColumn:@"url"];
NSLog(@"totalFileSize:%ld, url:%@", totalFileSize, url);
}
}];
修改資料:
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"UPDATE t_videoCaches SET totalFileSize = ? WHERE url = ?", [NSNumber numberWithInteger:2000], @"https://blog.csdn.net/hero_wqb"];
if (result) {
NSLog(@"修改成功");
}else {
NSLog(@"修改失敗");
}
}];
一些常用的sql語句:
創表:(其中table為自定義表名稱,若表已存在不會重複建立)
"CREATE TABLE IF NOT EXISTS table (id integer PRIMARY KEY AUTOINCREMENT, variableA integer, variableB text)"
插入資料:(?指代變數,需要我們傳入)
"INSERT INTO table (variableA, variableB) VALUES (?, ?)"
刪除資料:(通過變數A查找出資料並刪除)
"DELETE FROM table WHERE variableA = ?"
查詢資料:
通過變數A查尋變數B的值:
"SELECT variableB FROM table WHERE variableA = ?"
查詢整張表全部資料:(根據主鍵自增的順序返回)
"SELECT * FROM table"
通過變數A查詢資料:(根據主鍵自增的順序返回)
"SELECT * FROM table WHERE variableA = ?"
查詢變數A不滿足某條件的資料:(根據主鍵自增的順序返回)
"SELECT * FROM table WHERE variableA != ?"
通過變數A查詢資料:(根據變數B由大到小的順序返回,desc:倒序,asc:正序)
"SELECT * FROM table WHERE variableA = ? order by variableB desc"
通過變數A查詢資料:(根據變數B由小到大的順序返回第一條,limit 0,1:從第0個座標開始,取1條資料)
"SELECT * FROM table WHERE variableA = ? order by variableB asc limit 0,1"
修改資料:(通過變數A查詢資料,修改其變數B的值)
"UPDATE table SET variableB = ? WHERE variableA = ?"
封裝了一個單例,下面貼上程式碼:
.h檔案:#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSUInteger, HWDBUpdateOption) {
HWDBUpdateOptionState = 1 << 0, // 更新狀態
HWDBUpdateOptionLastStateTime = 1 << 1, // 更新狀態最後改變的時間
HWDBUpdateOptionResumeData = 1 << 2, // 更新下載的資料
HWDBUpdateOptionProgressData = 1 << 3, // 更新進度資料
HWDBUpdateOptionAllParam = 1 << 4 // 更新全部資料
};
@interface HWDataBaseManager : NSObject
// 獲取單例
+ (instancetype)shareManager;
// 插入資料
- (void)insertModel:(HWDownloadModel *)model;
// 獲取資料
- (HWDownloadModel *)getModelWithUrl:(NSString *)url; // 根據url獲取資料
- (HWDownloadModel *)getWaitingModel; // 獲取第一條等待的資料
- (HWDownloadModel *)getLastDownloadingModel; // 獲取最後一條正在下載的資料
- (NSArray<HWDownloadModel *> *)getAllCacheData; // 獲取所有資料
- (NSArray<HWDownloadModel *> *)getAllDownloadingData; // 根據lastStateTime倒敘獲取所有正在下載的資料
- (NSArray<HWDownloadModel *> *)getAllDownloadedData; // 獲取所有下載完成的資料
- (NSArray<HWDownloadModel *> *)getAllUnDownloadedData; // 獲取所有未下載完成的資料(包含正在下載、等待、暫停、錯誤)
- (NSArray<HWDownloadModel *> *)getAllWaitingData; // 獲取所有等待下載的資料
// 更新資料
- (void)updateWithModel:(HWDownloadModel *)model option:(HWDBUpdateOption)option;
// 刪除資料
- (void)deleteModelWithUrl:(NSString *)url;
@end
.m檔案:
#import "HWDataBaseManager.h"
typedef NS_ENUM(NSInteger, HWDBGetDateOption) {
HWDBGetDateOptionAllCacheData = 0, // 所有快取資料
HWDBGetDateOptionAllDownloadingData, // 所有正在下載的資料
HWDBGetDateOptionAllDownloadedData, // 所有下載完成的資料
HWDBGetDateOptionAllUnDownloadedData, // 所有未下載完成的資料
HWDBGetDateOptionAllWaitingData, // 所有等待下載的資料
HWDBGetDateOptionModelWithUrl, // 通過url獲取單條資料
HWDBGetDateOptionWaitingModel, // 第一條等待的資料
HWDBGetDateOptionLastDownloadingModel, // 最後一條正在下載的資料
};
@interface HWDataBaseManager ()
@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
@end
@implementation HWDataBaseManager
+ (instancetype)shareManager
{
static HWDataBaseManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
- (instancetype)init
{
if (self = [super init]) {
[self creatVideoCachesTable];
}
return self;
}
// 創表
- (void)creatVideoCachesTable
{
// 資料庫檔案路徑
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"HWDownloadVideoCaches.sqlite"];
// 建立佇列物件,內部會自動建立一個數據庫, 並且自動開啟
_dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
[_dbQueue inDatabase:^(FMDatabase *db) {
// 創表
BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_videoCaches (id integer PRIMARY KEY AUTOINCREMENT, vid text, fileName text, url text, resumeData blob, totalFileSize integer, tmpFileSize integer, state integer, progress float, lastSpeedTime integer, intervalFileSize integer, lastStateTime integer)"];
if (result) {
// HWLog(@"視訊快取資料表建立成功");
}else {
HWLog(@"視訊快取資料表建立失敗");
}
}];
}
// 插入資料
- (void)insertModel:(HWDownloadModel *)model
{
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"INSERT INTO t_videoCaches (vid, fileName, url, resumeData, totalFileSize, tmpFileSize, state, progress, lastSpeedTime, intervalFileSize, lastStateTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", model.vid, model.fileName, model.url, model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithInteger:model.state], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0]];
if (result) {
// HWLog(@"插入成功:%@", model.fileName);
}else {
HWLog(@"插入失敗:%@", model.fileName);
}
}];
}
// 獲取單條資料
- (HWDownloadModel *)getModelWithUrl:(NSString *)url
{
return [self getModelWithOption:HWDBGetDateOptionModelWithUrl url:url];
}
// 獲取第一條等待的資料
- (HWDownloadModel *)getWaitingModel
{
return [self getModelWithOption:HWDBGetDateOptionWaitingModel url:nil];
}
// 獲取最後一條正在下載的資料
- (HWDownloadModel *)getLastDownloadingModel
{
return [self getModelWithOption:HWDBGetDateOptionLastDownloadingModel url:nil];
}
// 獲取所有資料
- (NSArray<HWDownloadModel *> *)getAllCacheData
{
return [self getDateWithOption:HWDBGetDateOptionAllCacheData];
}
// 根據lastStateTime倒敘獲取所有正在下載的資料
- (NSArray<HWDownloadModel *> *)getAllDownloadingData
{
return [self getDateWithOption:HWDBGetDateOptionAllDownloadingData];
}
// 獲取所有下載完成的資料
- (NSArray<HWDownloadModel *> *)getAllDownloadedData
{
return [self getDateWithOption:HWDBGetDateOptionAllDownloadedData];
}
// 獲取所有未下載完成的資料
- (NSArray<HWDownloadModel *> *)getAllUnDownloadedData
{
return [self getDateWithOption:HWDBGetDateOptionAllUnDownloadedData];
}
// 獲取所有等待下載的資料
- (NSArray<HWDownloadModel *> *)getAllWaitingData
{
return [self getDateWithOption:HWDBGetDateOptionAllWaitingData];
}
// 獲取單條資料
- (HWDownloadModel *)getModelWithOption:(HWDBGetDateOption)option url:(NSString *)url
{
__block HWDownloadModel *model = nil;
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet;
switch (option) {
case HWDBGetDateOptionModelWithUrl:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE url = ?", url];
break;
case HWDBGetDateOptionWaitingModel:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime asc limit 0,1", [NSNumber numberWithInteger:HWDownloadStateWaiting]];
break;
case HWDBGetDateOptionLastDownloadingModel:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc limit 0,1", [NSNumber numberWithInteger:HWDownloadStateDownloading]];
break;
default:
break;
}
while ([resultSet next]) {
model = [[HWDownloadModel alloc] initWithFMResultSet:resultSet];
}
}];
return model;
}
// 獲取資料集合
- (NSArray<HWDownloadModel *> *)getDateWithOption:(HWDBGetDateOption)option
{
__block NSArray<HWDownloadModel *> *array = nil;
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet;
switch (option) {
case HWDBGetDateOptionAllCacheData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches"];
break;
case HWDBGetDateOptionAllDownloadingData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc", [NSNumber numberWithInteger:HWDownloadStateDownloading]];
break;
case HWDBGetDateOptionAllDownloadedData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:HWDownloadStateFinish]];
break;
case HWDBGetDateOptionAllUnDownloadedData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state != ?", [NSNumber numberWithInteger:HWDownloadStateFinish]];
break;
case HWDBGetDateOptionAllWaitingData:
resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:HWDownloadStateWaiting]];
break;
default:
break;
}
NSMutableArray *tmpArr = [NSMutableArray array];
while ([resultSet next]) {
[tmpArr addObject:[[HWDownloadModel alloc] initWithFMResultSet:resultSet]];
}
array = tmpArr;
}];
return array;
}
// 更新資料
- (void)updateWithModel:(HWDownloadModel *)model option:(HWDBUpdateOption)option
{
[_dbQueue inDatabase:^(FMDatabase *db) {
if (option & HWDBUpdateOptionState) {
[self postStateChangeNotificationWithFMDatabase:db model:model];
[db executeUpdate:@"UPDATE t_videoCaches SET state = ? WHERE url = ?", [NSNumber numberWithInteger:model.state], model.url];
}
if (option & HWDBUpdateOptionLastStateTime) {
[db executeUpdate:@"UPDATE t_videoCaches SET lastStateTime = ? WHERE url = ?", [NSNumber numberWithInteger:[HWToolBox getTimeStampWithDate:[NSDate date]]], model.url];
}
if (option & HWDBUpdateOptionResumeData) {
[db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ? WHERE url = ?", model.resumeData, model.url];
}
if (option & HWDBUpdateOptionProgressData) {
[db executeUpdate:@"UPDATE t_videoCaches SET tmpFileSize = ?, totalFileSize = ?, progress = ?, lastSpeedTime = ?, intervalFileSize = ? WHERE url = ?", [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.totalFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], model.url];
}
if (option & HWDBUpdateOptionAllParam) {
[self postStateChangeNotificationWithFMDatabase:db model:model];
[db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ?, totalFileSize = ?, tmpFileSize = ?, progress = ?, state = ?, lastSpeedTime = ?, intervalFileSize = ?, lastStateTime = ? WHERE url = ?", model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:model.state], [NSNumber numberWithInteger:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], [NSNumber numberWithInteger:[HWToolBox getTimeStampWithDate:[NSDate date]]], model.url];
}
}];
}
// 狀態變更通知
- (void)postStateChangeNotificationWithFMDatabase:(FMDatabase *)db model:(HWDownloadModel *)model
{
// 原狀態
NSInteger oldState = [db intForQuery:@"SELECT state FROM t_videoCaches WHERE url = ?", model.url];
if (oldState != model.state) {
// 狀態變更通知
[[NSNotificationCenter defaultCenter] postNotificationName:HWDownloadStateChangeNotification object:model];
}
}
// 刪除資料
- (void)deleteModelWithUrl:(NSString *)url
{
[_dbQueue inDatabase:^(FMDatabase *db) {
BOOL result = [db executeUpdate:@"DELETE FROM t_videoCaches WHERE url = ?", url];
if (result) {
// HWLog(@"刪除成功:%@", url);
}else {
HWLog(@"刪除失敗:%@", url);
}
}];
}
@end
寫部落格的初心是希望大家共同交流成長,博主水平有限難免有偏頗之處,歡迎批評指正。