在IOS開發中常常會須要存儲數據,對於比較少許的數據能夠採起文件的形式存儲,好比使用plist文件、歸檔等,可是對於大量的數據,就須要使用數據庫,在IOS開發中數據庫存儲能夠直接經過SQL訪問數據庫,也能夠經過ORM進行對象關係的映射,固然也能夠選擇使用第三方框架實現對數據庫的操做。在這裏,主要來說解一下第一種方式,SQLite。html
SQLiteios
數據庫有不少,分爲重量級和輕量級兩類,移動設備的內存比較小,所以須要選擇輕量級的數據庫。在移動設備上應用程序開發中使用數據庫,比較主流的是SQLite。SQLite支持跨平臺,雖然是輕量級的數據庫,可是它的功能很強大,其功能不亞於不少大型的關係數據庫。web
SQLite基於C語言開發的輕型數據庫,所以須要使用C語言語法進行數據庫操做、訪問,不能直接使用OC語言訪問數據庫。此外,SQLite中採用的是動態數據類型,即便建立時定義了一種類型,在實際操做時也能夠存儲其餘類型,可是推薦建庫時使用合適的類型,特別是應用須要考慮跨平臺的狀況時。sql
SQLite能夠直接在代碼中使用,可是在開發的過程當中,最好安裝一個能夠直接打開數據庫的工具,來驗證對數據庫的操做是否正確,方便程序調試。你們能夠去SQLite官方網站下載Mac OSX系統下的命令行工具,也可使用相似於SQLiteManager、MesaSQLite等工具。數據庫
數據庫的使用,主要包括對數據庫的打開關閉、建立表格、對數據庫中的數據進行增刪改查以及更新等操做,實際上也就是一般所講的SQL語句,SQLite中的SQL語法並無太大的差異,所以這裏對於SQL語句的內容不過多贅述,你們能夠參考其餘SQL相關的內容,在這裏,咱們來詳細講解一下在IOS開發中的SQLite的使用。框架
SQLite使用步驟:函數
1. 在項目中導入libsqlite3.0.dylib框架工具
2. 獲取數據庫的路徑,通常是得到得到沙盒中Document文件夾路徑,而後拼接獲得數據庫路徑網站
3. 建立或者打開數據庫,須要注意的是,在打開的時候須要使用C語言,所以須要先將路徑轉爲C的字符串,而後經過sqlite3_open()打開數據庫,若是文件存在則直接打開,不然建立並打開。根據sqlite3_open()返回值來判斷是否正確成功打開,若是成功打開,就可使用獲得的sqlite3類型的對象,來對數據庫進行其餘操做。spa
4. 執行寫好的SQL語句,對數據庫進行操做,執行SQL語句有兩種,一種是無返回值語句,好比建立、增長、刪除等,一種是有返回值的語句,好比查詢。
(1). 對於無返回值的語句(如增長、刪除、修改等)直接經過sqlite3_exec()函數執行,所以能夠封裝一個方法,用於除查詢之外的操做
(2). 對於有返回值的語句則首先經過sqlite3_prepare_v2()進行sql語句評估(語法檢測),而後經過sqlite3_step()依次取出查詢結果的每一行數據,對於每行數據均可以經過對應的sqlite3_column_類型()方法得到對應列的數據,如此反覆循環直到遍歷完成。固然,最後須要釋放句柄。
5. SQLite操做是持久鏈接,在整個操做過程當中無需管理數據庫鏈接,若是使用完畢,能夠選擇經過sqlite3_close()手動關閉數據庫
SQLite使用代碼
導入框架,如圖所示
// ViewController.m // JRSQLite查詢3 // // Created by jerehedu on 15/6/16. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import "ViewController.h" #import <sqlite3.h> @interface ViewController () { sqlite3 *db; //聲明數據庫對象 } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 得到數據庫路徑 // 得到沙盒中Document文件夾路徑 NSString *dbPath = [self getUserDocumentPath]; // 拼接獲得數據庫路徑 NSString *sqlitePath = [dbPath stringByAppendingPathComponent:@"test.sqlite"]; // 建立或打開數據庫 const char *p = [sqlitePath UTF8String]; int res = sqlite3_open(p, &db); if (res==SQLITE_OK) { NSLog(@"db open"); //<一>建立表格 NSString *sql = @"create table if not exists temps (t_id integer primary key autoincrement,t_name varchar(20) )"; if ([self execNoQueryWithSQL:sql]) { NSLog(@"table temps is created"); } //<二>插入數據 NSString *insert_Sql = @"insert into temps (t_name) values ('pear')"; if ([self execNoQueryWithSQL:insert_Sql]) { NSLog(@"table insert "); } //<三>刪除數據 NSString *delete_sql = @"delete from temps where t_id=2"; if ([self execNoQueryWithSQL:delete_sql]) { NSLog(@"table delete "); } //<四>修改數據 NSString *update_sql = @"update temps set t_name='ios' where t_id=1"; if ([self execNoQueryWithSQL:update_sql]) { NSLog(@"table update "); } //<五>查詢簡單的數據1 NSString *select_sql1 = @"select * from temps where t_id=1"; sqlite3_stmt *stmt1 = [self execQueryWithSQL:select_sql1]; while (sqlite3_step(stmt1) == SQLITE_ROW) { //按照當前列的類型選數據,列數從0開始 int t_id = sqlite3_column_int(stmt1, 0); const unsigned char *t_name = sqlite3_column_text(stmt1, 1); NSString *name = [NSString stringWithUTF8String:(char*)t_name]; NSLog(@"%i %@",t_id,name); } //釋放stmt statement sqlite3_finalize(stmt1); //<五>查詢數據2 參數化的sql語句 查找id>2 而且名字以p開頭的 //用?佔位 int seachId2 = 2; NSString *seach_name = @"p%"; NSString *seach_sql = @"select * from temps where t_id>? and t_name like ?"; sqlite3_stmt *stmt6 = [self execQueryWithSQL:seach_sql andWithParams:@[[NSNumber numberWithInt:seachId2],seach_name]]; //準備執行(至關於點擊run query),執行的時候是一行一行的執行 while (sqlite3_step(stmt6) == SQLITE_ROW) { //按照當前列的類型選數據,列數從0開始 int t_id = sqlite3_column_int(stmt6, 0); const unsigned char *t_name = sqlite3_column_text(stmt6, 1); NSString *name = [NSString stringWithUTF8String:(char*)t_name]; NSLog(@"..>>>>>>...%i %@",t_id,name); } sqlite3_finalize(stmt6); } // 關閉數據庫 sqlite3_close(db); } #pragma mark - 得到沙盒sandbox裏面document文件夾路徑 - (NSString *)getUserDocumentPath { NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPath = [path firstObject]; return documentPath; } #pragma mark - 執行除查找之外的數據庫操做方法 -(BOOL)execNoQueryWithSQL:(NSString*)sql { /* 執行 參數1:sqlite3 對象 參數2:c形式的 sql語句 參數3:回調函數 參數4:回調函數的參數 參數5:錯誤信息(能夠char類型指針接受錯誤信息,用來查錯使用) */ if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL) == SQLITE_OK) { return YES; } return NO; } #pragma mark 返回查詢結果集(簡單無參) -(sqlite3_stmt *)execQueryWithSQL:(NSString*)sql { //執行sql語句以後,返回的結果語句 sqlite3_stmt *stmt; /* 準備執行查詢的sql語句 (至關於把查詢語句寫好) 參數3:sql語句長度,一般用-1表示(系統會自動計算),也能夠用strlength函數計算 參數4:sql_stmt對象 (執行的對象) 參數5:未執行的sql語句 */ int pre_res = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL); //若是準備成功 if (pre_res == SQLITE_OK) { return stmt; } return NULL; } #pragma mark - 返回查詢結果集(有參數的) -(sqlite3_stmt *)execQueryWithSQL:(NSString *)sql andWithParams:(NSArray *)params { sqlite3_stmt *stmt; int pre_res = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL); if (pre_res == SQLITE_OK) { //有參數,循環綁定參數 if (params!=nil) { for (int i=0; i<params.count; i++) { id obj = params[i]; //綁定的數據類型可能爲NSString或者NSNumber,或者數據爲空,分別判斷 if (obj==nil) { //若是數據爲nil sqlite3_bind_null(stmt, i+1); } else if ([obj respondsToSelector:@selector(objCType)]) { //當前的綁定的數據類型位NSNumber //NSNumber判斷包裝的是int?longInt?shortInt?float?double? /* strstr(參數1,參數2) (strstr() c中函數搜索一個字符串在另外一個字符串中的第一次出現,則該函數返回第一次匹配的字符串的地址,找不到返回NULL) 判斷參數1中的字符在參數2的字符串char*中出現的索引 [obj objCType] 若是obj是int返回字符串i */ if (strstr("ilsILS", [obj objCType])) { /* 綁定參數 若是有where 參數1:sqlite_stmt對象 (statement結果集) 參數2:佔位符索引 從1開始 參數3:替代佔位符的真實參數 */ sqlite3_bind_int(stmt, i+1, [obj intValue]); } else if (strstr("fdFD", [obj objCType])) { sqlite3_bind_double(stmt, i+1, [obj doubleValue]); } else { stmt = nil; } } else if ([obj respondsToSelector:@selector(UTF8String)]) { //當前的綁定的數據類型位NSString 判斷是否有UTF8String方法 //用bind替換佔位符 索引從1開始 sqlite3_bind_text(stmt, i+1, [obj UTF8String], -1, NULL); } else { stmt = nil; } } return stmt; } } return NULL; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
疑問諮詢或技術交流,請加入官方QQ羣: (452379712)