使用iOS原生sqlite3框架對sqlite數據庫進行操作
使用iOS原生sqlite3框架對sqlite數據庫進行操作
一、引言
sqlite數據庫是一種小型數據庫,由于其小巧與簡潔,在移動開發領域應用深廣,sqlite數據庫有一套完備的sqlite語句進行管理操作,一些常用的語句和可視化的開發工具在上篇博客中有介紹,地址如下:
sqlite數據庫常用語句及可視化工具介紹:http://my.oschina.net/u/2340880/blog/600820。
在iOS的原生開發框架中可以對sqlite數據庫進行很好的支持,這個框架中采用C風格且通過指針移動進行數據的操作,使用起來有些不便,我們可以對一些數據庫的常用操作進行一些面向對象的封裝。
二、libsqlite3系統庫中操作數據庫的常用方法
libsqlite3是對sqlite數據庫進行操作的系統庫,在使用前,我們需要先導入,點擊Xcode的Build Phases標簽,展開Link Binary With Libraries,點擊+號,在彈出的窗口中搜索libsqlite3.0,將其導入進工程,過程如下圖:


在需要操作sqlite數據的文件中導入如下頭文件:
#import <sqlite3.h>
數據庫文件的操作是由一個sqlite3類型的指針操作管理的,如下方法進行數據庫的打開:
sqlite3 *sqlite; sqlite3_open(dataBaePath, &sqlite)
sqlite3_open方法返回一個int值,實際上,在使用libsqlite3框架中的大多方法時都會返回一個int值,這個int值代表著方法執行的相應結果狀態,這些狀態再sqlite3.h文件中通過宏來定義,列舉如下:
#define SQLITE_OK 0 //操作成功 /* 以下是錯誤代碼 */ #define SQLITE_ERROR 1 /* SQL數據庫錯誤或者丟失*/ #define SQLITE_INTERNAL 2 /* SQL內部邏輯錯誤 */ #define SQLITE_PERM 3 /* 沒有訪問權限 */ #define SQLITE_ABORT 4 /* 回調請求終止 */ #define SQLITE_BUSY 5 /* 數據庫文件被鎖定 */ #define SQLITE_LOCKED 6 /* 數據庫中有表被鎖定 */ #define SQLITE_NOMEM 7 /* 分配空間失敗 */ #define SQLITE_READONLY 8 /* 企圖向只讀屬性的數據庫中做寫操作 */ #define SQLITE_INTERRUPT 9 /* 通過sqlite3_interrupt()方法終止操作*/ #define SQLITE_IOERR 10 /* 磁盤發生錯誤 */ #define SQLITE_CORRUPT 11 /* 數據庫磁盤格式不正確 */ #define SQLITE_NOTFOUND 12 /* 調用位置操作碼 */ #define SQLITE_FULL 13 /* 由于數據庫已滿造成的添加數據失敗 */ #define SQLITE_CANTOPEN 14 /* 不法打開數據庫文件 */ #define SQLITE_PROTOCOL 15 /* 數據庫鎖協議錯誤 */ #define SQLITE_EMPTY 16 /* 數據庫為空 */ #define SQLITE_SCHEMA 17 /* 數據庫模式更改 */ #define SQLITE_TOOBIG 18 /* 字符或者二進制數據超出長度 */ #define SQLITE_CONSTRAINT 19 /* 違反協議終止 */ #define SQLITE_MISMATCH 20 /* 數據類型不匹配 */ #define SQLITE_MISUSE 21 /* 庫使用不當 */ #define SQLITE_NOLFS 22 /* 使用不支持的操作系統 */ #define SQLITE_AUTH 23 /* 授權拒絕 */ #define SQLITE_FORMAT 24 /* 輔助數據庫格式錯誤 */ #define SQLITE_RANGE 25 /* sqlite3_bind 第二個參數超出范圍 */ #define SQLITE_NOTADB 26 /* 打開不是數據庫的文件 */ #define SQLITE_NOTICE 27 /* 來自sqlite3_log()的通知 */ #define SQLITE_WARNING 28 /* 來自sqlite3_log() 的警告*/ #define SQLITE_ROW 100 /* sqlite3_step() 方法準備好了一行數據 */ #define SQLITE_DONE 101 /* sqlite3_step() 已完成執行*/
執行非查詢類的語句,例如創建,添加,刪除等操作,使用如下方法:
char * err; sqlite3 *sql; sqlite3_exec(sql, sqlStr, NULL, NULL, &err);
sqlite3_exec方法中第一個參數為成功執行了打開數據庫操作的sqlite3指針,第二個參數為要執行的sql語句,最后一個參數為錯誤信息字符串。
執行查詢語句的方法比較復雜,通過如下方法:
sqlite3 * sqlite;
sqlite3_stmt *stmt =nil;
int code = sqlite3_prepare_v2(sqlite, sqlStr, -1, &stmt, NULL);
while (sqlite3_step(stmt)==SQLITE_ROW) {
char * cString =(char*)sqlite3_column_text(stmt, 0);
NSString * value = [NSString stringWithCString:cString?cString:"NULL" encoding:NSUTF8StringEncoding];
NSNumber * value = [NSNumber numberWithLongLong:sqlite3_column_int64(stmt, 1)];
}
sqlite3_finalize(stmt);
stmt是一個數據位置指針,標記查詢到數庫的數據位置,sqlite3_prepare_v2()方法進行數據庫查詢的準備工作,第一個參數為成功打開的數據庫指針,第二個參數為要執行的查詢語句,第三個參數為sqlite3_stmt指針的地址,這個方法也會返回一個int值,作為標記狀態是否成功。
sqlite3_step方法對stmt指針進行移動,會逐行進行移動,這個方法會返回一個int值,如果和SQLITE_ROW宏對應,則表明有此行數據,可以通過while循環來對數據進行讀取。
sqlite3_column_XXX()是取行中每一列的數據,根據數據類型的不同,sqlite3_column_XXX()有一系列對應的方法,這個方法中第一個參數是stmt指針,第二個參數為列序號。
sqlite3_finalize()方法對stmt指針進行關閉。
三、面向對象的sqlite數據庫操作框架封裝
網上不乏有許多優秀的第三方sqlite數據庫使用框架,FFDM就是其中之一,并且apple自帶的coreData也十分優秀。這篇博客中所述內容并不全面,代碼也并不十分完善健壯,封裝出來的代碼除了能夠完成基本的數據庫操作外,更多主要是對設計思路的示例。
1.面向對象的sqlite管理類的設計思路
為了便于使用,在設計時,我們盡量將libsqlite3中的方法不暴漏在使用層,通過面向應用的接口來進行方法的設計,設計思路類圖如下:

圖中,文件管理中心對文件進行存取刪改管理,不暴漏在外,數據庫管理中心負責對數據庫的創建,刪除打開等操作,具體的數據操作由數據庫操作對象來完成。
2.文件管理中心方法的編寫
文件管理中心主要負責對數據庫文件的存取,可以實現如下方法:
YHBaseCecheCenter.h
/** * @brief 獲取數據庫方法的地址 * * @return 地址字符串 * */ -(NSString *)getDataBaseFilePath; /** * @brief 獲取某個數據庫的大小 * * @param name 數據庫名稱 * * @return 文件大小 單位M * */ -(float)getSizeFromDataBaseName:(NSString *)name;
YHBaseCecheCenter.m
-(NSString *)getDataBaseFilePath{
return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
}
-(float)getSizeFromDataBaseName:(NSString *)name{
NSString * path = [NSString stringWithFormat:@"/%@/%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject,name];
return [self fileSizeAtPath:path]/(1024.0*1024.0);
}
//獲取文件大小
- (long long) fileSizeAtPath:(NSString*) filePath{
NSFileManager* manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePath]){
return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
}
return 0;
}
在iOS系統中因為其沙盒結構的限制,數據庫必須方法documents目錄下才能正常打開使用。
3.數據庫管理中心的設計
數據庫管理中心主要負責對數據庫的宏觀操作,采用類方法的設計模式,如下
YHBaseSQLiteManager.h
/** * @brief 打開一個數據庫 如果不存在則會創建 * * @param name 數據庫名稱 * * @return 數據庫操作對象 如果創建失敗會返回nil * */ +(YHBaseSQLiteContext *)openSQLiteWithName:(NSString *)name; /** * @brief 獲取數據庫文件的大小 單位M * * @param dataBase 數據庫上下文對象 * * @return 數據庫文件大小 */ +(float)getSizeOfDataBase:(YHBaseSQLiteContext *)dataBase; /** * @brief 獲取數據庫文件的大小 單位M * * @param dataBaseName 數據庫名稱 * * @return 數據庫文件大小 */ +(float)getSizeOfDataBaseName:(NSString *)dataBaseName; /** * @brief 刪除所有數據庫 * */ +(void)removeDataBase;
YHBaseSQLiteManager.m
+(YHBaseSQLiteContext *)openSQLiteWithName:(NSString *)name{
NSString * path = [[YHBaseCecheCenter sharedTheSingletion]getDataBaseFilePath];
YHBaseSQLiteContext * context = [[YHBaseSQLiteContext alloc]init];
context.name = name;
BOOL success = [context openDataBaeWithName:[NSString stringWithFormat:@"%@/%@",path,name]];
if (success) {
return context;
}else{
return nil;
}
}
+(float)getSizeOfDataBase:(YHBaseSQLiteContext *)dataBase{
return [[YHBaseCecheCenter sharedTheSingletion]getSizeFromDataBaseName:dataBase.name];
}
+(float)getSizeOfDataBaseName:(NSString *)dataBaseName{
return [[YHBaseCecheCenter sharedTheSingletion]getSizeFromDataBaseName:dataBaseName];
}
+(void)removeDataBase{
NSString * path = [[YHBaseCecheCenter sharedTheSingletion]getDataBaseFilePath];
return [[YHBaseCecheCenter sharedTheSingletion]removeCacheFromPath:path];
}
4.數據庫操作對象
將操作數據庫的核心方法封裝在這個類中:
YHBaseSQLiteContext.h
/** *操作的數據庫名稱 */ @property(nonatomic,strong)NSString * name; /** *內含sqlite3 對象 */ @property(nonatomic,assign)sqlite3 * sqlite3_db; /** * @brief 打開一個數據庫 不存在則創建 * * @param path 數據庫路徑 * * @return 是否操作成功 */ -(BOOL)openDataBaeWithName:(NSString *)path; /** * @brief 再數據庫中創建一張表 如果已經存在 會返回錯誤信息 * * @param name 表的名稱 * * @prarm dic 表中的鍵 其中字典中需傳入 鍵名:類型 類型的宏定義在YHBaseSQLTypeHeader.h中 * * @param callBack 結果回調 */ -(void)createTableWithName:(NSString *)name keysDictionary:(NSDictionary<NSString*,NSString*> *) dic callBack:(void (^)(YHBaseSQLError * error))complete; /** * @brief 向表中添加一條數據 * * @param dataDic 添加數據的鍵值對 * * @param name 插入表的名稱 * * @complete 回調 */ -(void)insertData:(NSDictionary<NSString *,id>*)dataDic intoTable:(NSString *)name callBack:(void (^)(YHBaseSQLError * error))complete; /** * @brief 向表中添加一個鍵 * * @param kName 添加的鍵 * * @prarm type 類型 * * @prarm tableName 表名稱 * * @prarm complete 結果回調 */ -(void)addKey:(NSString *)kName keyType:(NSString *)type intoTable:(NSString *)tableName callBack:(void(^)(YHBaseSQLError *error))complete; /** * @brief 修改數據 * * @param dataDic 新的鍵值 * * @param wlStr 條件字符串 一般通過主鍵找到對應數據修改 可以為nil * * @param complete 結果回調 */ -(void)update:(NSDictionary<NSString*,id> *)dataDic inTable:(NSString *)tableName whileString:(NSString *)wlStr callBack:(void(^)(YHBaseSQLError * error))complete; /** * @brief 刪除數據 * * @param tableName 表名 * * @param wlStr 條件字符串 一般通過主鍵找到對應數據刪除 可以為nil 不傳這個參數將刪除所有數據 * */ -(void)deleteDataFromTable:(NSString *)tableName whereString:(NSString *)wlStr callBack:(void(^)(YHBaseSQLError * error))complete; /** * @brief 刪除一張表 * * @param tableName 表名 * */ -(void)dropTable:(NSString *)tableName callBack:(void(^)(YHBaseSQLError * error))complete; /** * @brief 查詢數據 * * @param keys 要查詢的鍵值 及其對應的數據類型 可以為nil則查詢全部 * * @param tableName 表名 * * @param orderKey 進行排序的鍵值 可以為nil 則不排序 * * @param type 排序方式 在YHBaseSQLTypeHeader中有宏定義 * * @param wlstr 查詢條件 同于查詢單個數據 * * @param complete dataArray為查詢到的數據 其內為字典 * */ -(void)selectKeys:(NSArray<NSDictionary *> *)keys fromTable:(NSString*)tableName orderBy:(NSString *)orderKey orderType:(NSString *)type whileStr:(NSString *)wlstr callBack:(void(^)(NSArray<NSDictionary *> * dataArray,YHBaseSQLError * error))complete; /** * @brief 關閉數據庫上下文操作 * 調用此方法后 這個context對象將不再有效 如果再需要使用 需要YHBaseSQLiteManager中的類方法再次返回 */ -(void)closeContext;
YHBaseSQLiteContext.m
-(BOOL)openDataBaeWithName:(NSString *)path{
if (sqlite3_open([path UTF8String], &_sqlite3_db)!=SQLITE_OK) {
sqlite3_close(_sqlite3_db);
_sqlite3_db=nil;
return NO;
}else{
return YES;
}
}
-(void)createTableWithName:(NSString *)name keysDictionary:(NSDictionary<NSString *,NSString *> *)dic callBack:(void (^)(YHBaseSQLError *))complete{
NSMutableString * keys = [[NSMutableString alloc]init];
for (int i=0; i<dic.allKeys.count; i++) {
NSString * key = dic.allKeys[i];
if (i<dic.allKeys.count-1) {
[keys appendFormat:@"%@ %@,",key,[dic objectForKey:key]];
}else{
[keys appendFormat:@"%@ %@",key,[dic objectForKey:key]];
}
}
NSString * sqlStr = [NSString stringWithFormat:@"create table %@(%@)",name,keys];
[self runSQL:sqlStr callBack:^(YHBaseSQLError * error) {
if (complete) {
complete(error);
}
}];
}
-(void)insertData:(NSDictionary<NSString *,id> *)dataDic intoTable:(NSString *)name callBack:(void (^)(YHBaseSQLError *))complete{
NSMutableString * keys = [[NSMutableString alloc]init];
NSMutableString * values = [[NSMutableString alloc]init];
for (int i=0; i<dataDic.allKeys.count; i++) {
NSString * key = dataDic.allKeys[i];
if (i<dataDic.count-1) {
[keys appendFormat:@"%@,",key];
[values appendFormat:@"\"%@\",",[dataDic objectForKey:key]];
}else{
[keys appendFormat:@"%@",key];
[values appendFormat:@"\"%@\"",[dataDic objectForKey:key]];
}
}
NSString * sqlStr = [NSString stringWithFormat:@"insert into %@(%@) values(%@)",name,keys,values];
[self runSQL:sqlStr callBack:^(YHBaseSQLError *error) {
if (complete) {
complete(error);
}
}];
}
-(void)addKey:(NSString *)kName keyType:(NSString *)type intoTable:(NSString *)tableName callBack:(void (^)(YHBaseSQLError *))complete{
NSString * sqlStr = [NSString stringWithFormat:@"alter table %@ add %@ %@",tableName,kName,type];
[self runSQL:sqlStr callBack:^(YHBaseSQLError *error) {
if (complete) {
complete(error);
}
}];
}
-(void)update:(NSDictionary<NSString *,id> *)dataDic inTable:(NSString *)tableName whileString:(NSString *)wlStr callBack:(void (^)(YHBaseSQLError *))complete{
NSMutableString * sqlStr = [[NSMutableString alloc]init];
[sqlStr appendFormat:@"update %@ set ",tableName];
for (int i=0; i<dataDic.allKeys.count; i++) {
NSString * key = dataDic.allKeys[i];
if (i<dataDic.allKeys.count-1) {
[sqlStr appendFormat:@"%@=\"%@\",",key,[dataDic objectForKey:key]];
}else{
[sqlStr appendFormat:@"%@=\"%@\"",key,[dataDic objectForKey:key]];
if (wlStr!=nil) {
[sqlStr appendFormat:@" where %@",wlStr];
}
}
}
[self runSQL:sqlStr callBack:^(YHBaseSQLError *error) {
if (complete) {
complete(error);
}
}];
}
-(void)deleteDataFromTable:(NSString *)tableName whereString:(NSString *)wlStr callBack:(void (^)(YHBaseSQLError *))complete{
NSMutableString * sqlStr = [[NSMutableString alloc]init];
[sqlStr appendFormat:@"delete from %@",tableName];
if (wlStr!=nil) {
[sqlStr appendFormat:@" where %@",wlStr];
}
[self runSQL:sqlStr callBack:^(YHBaseSQLError *error) {
if (complete) {
complete(error);
}
}];
}
-(void)dropTable:(NSString *)tableName callBack:(void (^)(YHBaseSQLError *))complete{
NSString * sqlStr = [NSString stringWithFormat:@"drop table %@",tableName];
[self runSQL:sqlStr callBack:^(YHBaseSQLError *error) {
if (complete) {
complete(error);
}
}];
}
-(void)selectKeys:(NSArray<NSDictionary *> *)keys fromTable:(NSString *)tableName orderBy:(NSString *)orderKey orderType:(NSString *)type whileStr:(NSString *)wlstr callBack:(void (^)(NSArray<NSDictionary *> *, YHBaseSQLError *))complete{
NSMutableString * sqlStr = [[NSMutableString alloc]init];
[sqlStr appendFormat:@"select"];
if (keys==nil||keys.count==0) {
[sqlStr appendFormat:@" * from %@",tableName];
}else{
for (int i=0; i<keys.count; i++) {
if (i<keys.count-1) {
[sqlStr appendFormat:@" %@,",keys[i].allKeys.firstObject];
}else{
[sqlStr appendFormat:@" %@ from %@",keys[i].allKeys.firstObject,tableName];
}
}
}
if (wlstr) {
[sqlStr appendFormat:@" where %@",wlstr];
}
if (orderKey) {
[sqlStr appendFormat:@" order by %@",orderKey];
}
if (type) {
[sqlStr appendFormat:@" %@",type];
}
NSMutableArray * keysArr = [[NSMutableArray alloc]init];
NSMutableArray * keysTypeArr = [[NSMutableArray alloc]init];
if (keys==nil||keys.count==0) {
NSArray<NSDictionary *> * tmpArr = [self getTheTableAllKeys:tableName];
for (int i=0; i<tmpArr.count; i++) {
NSString * key = tmpArr[i].allKeys.firstObject;
[keysArr addObject:key];
[keysTypeArr addObject:[tmpArr[i] objectForKey:key]];
}
}else{
for (int i=0; i<keys.count; i++) {
NSString * key = keys[i].allKeys.firstObject;
[keysArr addObject:key];
[keysTypeArr addObject:[keys[i] objectForKey:key]];
}
}
[self runSelectSQL:sqlStr withKeys:keysArr withDataType:keysTypeArr callBack:^(NSArray<NSDictionary *> *dataArray, YHBaseSQLError *error) {
if (complete) {
complete(dataArray,error);
}
}];
}
-(void)closeContext{
sqlite3_close(_sqlite3_db);
_sqlite3_db = nil;
}
//內部方法 運行創建獨立的非查詢SQL語句
-(void)runSQL:(NSString *)sql callBack:(void(^)(YHBaseSQLError * error))complete{
char * err;
int code = sqlite3_exec(_sqlite3_db, [sql UTF8String], NULL, NULL, &err);
if (code!=SQLITE_OK) {
YHBaseSQLError * error = [[YHBaseSQLError alloc]init];
error.errorInfo = [NSString stringWithCString:err encoding:NSUTF8StringEncoding];
error.errorCode = code;
complete(error);
}else{
complete(nil);
}
}
//運行查詢語句
-(void)runSelectSQL:(NSString *)sql withKeys:(NSArray *)keys withDataType:(NSArray *)dataType callBack:(void(^)(NSArray<NSDictionary *> * dataArray, YHBaseSQLError * error))complete{
sqlite3_stmt *stmt =nil;
int code = sqlite3_prepare_v2(_sqlite3_db, [sql UTF8String], -1, &stmt, NULL);
if (code!=SQLITE_OK) {
YHBaseSQLError * error = [[YHBaseSQLError alloc]init];
error.errorInfo = @"查詢失敗";
error.errorCode=code;
complete(nil,error);
}else{
NSMutableArray * resultArray = [[NSMutableArray alloc]init];
while (sqlite3_step(stmt)==SQLITE_ROW) {
//數據類型的分別解析
NSMutableDictionary * dic = [[NSMutableDictionary alloc]init];
for (int i=0; i<dataType.count; i++) {
NSString * type = dataType[i];
if ([type isEqualToString:YHBASE_SQL_DATATYPE_BINARY]) {
int length = sqlite3_column_bytes(stmt, i);
const void *data = sqlite3_column_blob(stmt, i);
NSData * value = [NSData dataWithBytes:data length:length];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_BLOB]){
int length = sqlite3_column_bytes(stmt, i);
const void *data = sqlite3_column_blob(stmt, i);
NSData * value = [NSData dataWithBytes:data length:length];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_BOOLEAN]){
NSNumber * value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_CURRENCY]){
NSNumber * value = [NSNumber numberWithLong:sqlite3_column_int64(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_DATE]){
char * cString =(char*)sqlite3_column_text(stmt, i);
NSString * value = [NSString stringWithCString:cString?cString:"NULL" encoding:NSUTF8StringEncoding];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_DOUBLE]){
NSNumber * value = [NSNumber numberWithFloat:sqlite3_column_double(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_FLOAT]){
NSNumber * value = [NSNumber numberWithFloat:sqlite3_column_double(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_INTRGER]){
NSNumber * value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_REAL]){
NSNumber * value = [NSNumber numberWithDouble:sqlite3_column_int(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_SMALLINT]){
NSNumber * value = [NSNumber numberWithShort:sqlite3_column_int(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_TEXT]){
char * cString =(char*)sqlite3_column_text(stmt, i);
NSString * value = [NSString stringWithCString:cString?cString:"NULL" encoding:NSUTF8StringEncoding];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_TIME]){
char * cString =(char*)sqlite3_column_text(stmt, i);
NSString * value = [NSString stringWithCString:cString?cString:"NULL" encoding:NSUTF8StringEncoding];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_TIMESTAMP]){
NSNumber * value = [NSNumber numberWithLongLong:sqlite3_column_int64(stmt, i)];
[dic setObject:value forKey:keys[i]];
}else if([type isEqualToString:YHBASE_SQL_DATATYPE_VARCHAR]){
char * cString =(char*)sqlite3_column_text(stmt, i);
NSString * value = [NSString stringWithCString:cString?cString:"NULL" encoding:NSUTF8StringEncoding];
[dic setObject:value forKey:keys[i]];
}
}
[resultArray addObject:dic];
}
sqlite3_finalize(stmt);
stmt=nil;
complete(resultArray,nil);
}
}
//獲取表中所有字段名和類型
-(NSArray<NSDictionary *> *)getTheTableAllKeys:(NSString *)tableName{
NSMutableArray * array = [[NSMutableArray alloc]init];
NSString * getColumn = [NSString stringWithFormat:@"PRAGMA table_info(%@)",tableName];
sqlite3_stmt *statement;
sqlite3_prepare_v2(_sqlite3_db, [getColumn UTF8String], -1, &statement, nil);
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameData = (char *)sqlite3_column_text(statement, 1);
NSString *columnName = [[NSString alloc] initWithUTF8String:nameData];
char *typeData = (char *)sqlite3_column_text(statement, 2);
NSString *columntype = [NSString stringWithCString:typeData encoding:NSUTF8StringEncoding];
NSDictionary * dic = @{columnName:columntype};
[array addObject:dic];
}
sqlite3_finalize(statement);
statement=nil;
return array;
}
5.錯誤信息類可以將數據庫操作中的異常拋出提示開發者
YHBaseSQLError.h
/** *異常的提示信息 */ __PROPERTY_NO_STRONG__(NSString *, errorInfo); /** *異常的對應code碼 */ __PROPERTY_NO_ASSIGN__(NSInteger, errorCode);
還有一個頭文件中定義了sqlite數據庫支持的數據類型和排序宏定義:
YHBaseSQLTypeHeader.h
#define YHBASE_SQL_DATATYPE_SMALLINT @"smallint" //short #define YHBASE_SQL_DATATYPE_INTRGER @"integer" //int #define YHBASE_SQL_DATATYPE_REAL @"real" //實數 #define YHBASE_SQL_DATATYPE_FLOAT @"float" //float #define YHBASE_SQL_DATATYPE_DOUBLE @"double" //double #define YHBASE_SQL_DATATYPE_CURRENCY @"currency" //long #define YHBASE_SQL_DATATYPE_VARCHAR @"varchar" //char #define YHBASE_SQL_DATATYPE_TEXT @"text" //string #define YHBASE_SQL_DATATYPE_BINARY @"binary" //二進制 #define YHBASE_SQL_DATATYPE_BLOB @"blob" //長二進制 #define YHBASE_SQL_DATATYPE_BOOLEAN @"boolean" //bool #define YHBASE_SQL_DATATYPE_DATE @"date" //日期 #define YHBASE_SQL_DATATYPE_TIME @"time" //時間 #define YHBASE_SQL_DATATYPE_TIMESTAMP @"timestamp"http://時間戳 #define YHBASE_SQL_ORDERTYPE_ASC @"asc" //升序 #define YHBASE_SQL_ORDERTYPE_DESC @"desc" //降序
四、使用
在使用時,直接調用context的相應方法操作數據庫即可,例如:
YHBaseSQLiteContext * context = [YHBaseSQLiteManager openSQLiteWithName:@"testDataBase"];
if (context) {
[context selectKeys:nil fromTable:@"MySQL" orderBy:@"age" orderType:YHBASE_SQL_ORDERTYPE_DESC whileStr:@"age>18" callBack:^(NSArray<NSDictionary *> *dataArray, YHBaseSQLError *error) {
NSLog(@"%@",dataArray);
NSLog(@"%@",error.errorInfo);
[context closeContext];
}];
}
上面的代碼將查詢textDataBase數據庫中MySQL表里所有age列大于18的數據,并按照age從小到大進行排序,數據結果在回調的dataArray中。
外:完整的代碼在下面的git地址中,這個git項目是一個基礎的開發框架,里面封裝了許多開發和調試常用功能,代碼不完善之處,希望多多交流,QQ316045346.