SQLite,是一款輕型的資料庫,是遵守ACID的關係型資料庫管理系統,它的設計目標是嵌入式的,而且目前已經在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式裝置中,可能只需要幾百K的記憶體就夠了。它能夠支援Windows/Linux/Unix等等主流的作業系統,同時能夠跟很多程式語言相結合,比如 Tcl、C#、PHP、Java等,還有ODBC介面,同樣比起Mysql、PostgreSQL這兩款開源的世界著名資料庫管理系統來講,它的處理速度比他們都快。SQLite第一個Alpha版本誕生於2000年5月。 至今已經有14個年頭,SQLite也迎來了一個版本 SQLite 3已經發布。
SQLite的特性
1. ACID事務
ACID,是指在可靠資料庫管理系統(DBMS)中,事務(transaction)所應該具有的四個特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability). 原子性意味著資料庫中的事務執行是作為原子。即不可再分,整個語句要麼執行,要麼不執行。一致性指資料庫事務不能破壞關係資料的完整性以及商務邏輯上的一致性。例如對銀行轉帳事務,不管事務成功還是失敗,應該保證事務結束後ACCOUNTS表中Tom和Jack的存款總額為2000元。事務的隔離性是多個使用者並發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作資料所幹擾,多個並發事務之間要相互隔離。持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
2. 零配置 – 無需安裝和管理配置
3.儲存在單一磁碟檔案中的一個完整的資料庫
4.資料庫檔案可以在不同位元組順序的機器間自由的共用
5.支援資料庫大小至2TB
6. 足夠小, 大致13萬行C代碼, 4.43M
7. 比一些流行的資料庫在大部分普通資料庫操作要快
8. 簡單, 輕鬆的API
9. 包含TCL綁定, 同時通過Wrapper支援其他語言的綁定
10. 良好注釋的原始碼, 並且有著90%以上的測試覆蓋率
11. 獨立,沒有額外依賴
12. 源碼完全的開源, 你可以用於任何用途, 包括出售它
13. 支援多種開發語言,C, PHP, Perl, Java, C#,Python, Ruby
SQLite在iOS中的基本使用
在iOS開發中可以用一些SQLite資料庫管理工具,例如SQLiteManager。
接下來就通過代碼來講述iOS中如何使用sqlite
sqlite.h檔案的引入
首先是開啟和關閉資料庫,開啟和建立資料庫都是sqlite3_open函數,如果filename已經建立那就是開啟。
NSString *filename;//資料庫檔案路徑sqlite3 *database; //sqlite3資料庫控制代碼的指標//開啟資料庫- (int) open{int rc=sqlite3_open([filename UTF8String], &database);if (rc) {sqlite3_close(database);NSLog(@"open database failed");}return rc;}//關閉資料庫- (void) close{if (database!=NULL) {sqlite3_close(database);}}接下來插入、刪除、更新都是用sqlite3_exec函數,記住執行語句,必須要先開啟資料庫,完成之後需要關閉資料庫。//執行 insert,update,delete 等非查詢SQL語句- (int)executeNonQuery:(NSString *)sql error:(NSError **)error {int rc;char *errmsg;rc = [self open];if (rc) { //錯誤處理if (error != NULL) {NSDictionary *eDict =[NSDictionary dictionaryWithObject:@"open database failed"forKey:NSLocalizedDescriptionKey];*error =[NSError errorWithDomain:kSqliteErrorDomain code:rc userInfo:eDict];}return rc;}rc = sqlite3_exec(database, [sql UTF8String], NULL, NULL, &errmsg);if (rc != SQLITE_OK) {if (error != NULL) {NSDictionary *eDict =[NSDictionary dictionaryWithObject:@"exec sql error"forKey:NSLocalizedDescriptionKey];*error =[NSError errorWithDomain:kSqliteErrorDomain code:rc userInfo:eDict];}NSLog(@"%s", errmsg);sqlite3_free(errmsg);}[self close];return rc;}
上面函數中sqlite3_free就是釋放存放錯誤資訊的記憶體空間。查詢操作會略顯複雜,同樣需要有開關資料庫的操作,不過有一個準備結果集和最後釋放結果集的操作,分別是sqlite3_prepare_v2和sqlite3_finalize,sqlite3_stmt就是結果集,下面就是具體操作。
[self open];// 查strsql = "select * from users";// SQLITE_API int sqlite3_prepare_v2(// sqlite3 *db, /* Database handle */// const char *zSql, /* SQL statement*/// int nByte, /* 結果集的最大長度。*/// sqlite3_stmt **ppStmt, /* OUT: 結果集 */// const char **pzTail /* OUT:指向結果集沒有用到的記憶體部分的指標。 */// );sqlite3_stmt* rc;//陳述式控制代碼if (sqlite3_prepare_v2(db, strsql, -1, &rc, NULL)!=SQLITE_OK) {}// sqlite3_step講結果集資料指標指向下一個元素。// 這個函數的傳回值如果是SQLITE_ROW就表示我們的結果集裡面有資料。// 否則我們的結果集就是空的。while (sqlite3_step(rc)==SQLITE_ROW) {// sqlite3_column系列函數。一般有兩個輸入參數。第一個是結果集指標,第二是資料所在列的序號。// 比如我們現在用的sqlite3_column_int和sqlite3_column_text。printf("id:%d | username:%s | password:%s \n",sqlite3_column_int(rc, 0),sqlite3_column_text(rc, 1),sqlite3_column_text(rc, 2));}// 查完後一定要釋放結果集。sqlite3_finalize(rc);[self close];
資料庫加密
免費版的SQLite有一個致命缺點:不支援加密。這就導致儲存在SQLite中的資料可以被任何人用任何文字編輯器查看到。
對資料庫加密的思路有兩種:
1. 將內容加密後再寫入資料庫
這種方式使用簡單,在入庫/出庫只需要將欄位做對應的加解密操作即可,一定程度上解決了將資料赤裸裸暴露的問題。
不過這種方式並不是徹底的加密,因為資料庫的表結構等資訊還是能被查看到。另外寫入資料庫的內容加密後,搜尋也是個問題。
2. 對資料庫檔案加密
將整個資料庫整個檔案加密,這種方式基本上能解決資料庫的資訊安全問題。目前已有的SQLite加密基本都是通過這種方式實現的。這裡就介紹一個開源的加密工具SQLCipher,安裝方法可以參照官網文檔,https://www.zetetic.net/sqlcipher/ios-tutorial/,SQLCipher使用256-bit AES加密,由於其基於免費版的SQLite,主要的加密介面和SQLite是相同的,但也增加了一些自己的介面。
其實SQLite的兩個加密函數使用起來非常的簡單,下面分情況說明:
1 給一個未加密的資料庫添加密碼:如果想要添加密碼,則可以在開啟資料庫檔案之後,關閉資料庫檔案之前的任何時刻調用sqlite3_key函數即可,該函數有三個參數,其中第一個參數為資料庫物件,第二個參數是要設定的密碼,第三個是密碼的長度。例如:sqlite3_key(db,”1q2w3e4r”,8); //給資料庫設定密碼1q2w3e4r
2 讀取一個加密資料庫中的資料:完成這個任務依然十分簡單,你只需要在開啟資料庫之後,再次調用一下sqlite3_key函數即可,例如,資料庫密碼是123456時,你只需要在代碼中加入sqlite3_key(db,”123456″,6);
3更改資料庫密碼:首先你需要使用當前的密碼正確的開啟資料庫,之後你可以調用sqlite3_rekey(db,”112233″,6) 來更改資料庫密碼。
4 刪除密碼:也就是把資料庫恢複到明文狀態。這時你仍然只需要調用sqlite3_rekey函數,並且把該函數的第二個參數置為NULL或者””,或者把第三個參數設為0。
事務操作
那麼問題又來了,如果iOS的sqlite同時插入或者查詢10000條資料,你該怎麼辦?
這裡有三步要做,第一,減少開關資料庫操作,插入10000條資料,不能開關10000次資料庫,只能進行一次開關;
第二,就是不能放在主線程;
第三,最重要的一點就是加入事務操作。
事務(Transaction)是訪問並可能更新資料庫中各種資料項目的一個程式執行單元(unit)。在sqlite插入資料的時候預設一條語句就是一個事務,有多少條資料就有多少次磁碟操作。所以10000次磁碟操作可能幾分鐘都做不完,這個時候需要把10000條語句都封裝成一個事務。
下面就是開始事務和提交事務的代碼了
-(int)beginService{char *errmsg;int rc = sqlite3_exec(database, "BEGIN transaction", NULL, NULL, &errmsg);return rc;}-(int)commitService{char *errmsg;int rc = sqlite3_exec(database, "COMMIT transaction", NULL, NULL, &errmsg);return rc;}
接下來就把三個操作合并
-(int)addModelsTest:(NSArray *)models error:(NSError **) error{char *errmsg;__block NSMutableArray *sqls=[NSMutableArray array];__block NoticeModel *aModel=[[NoticeModel alloc] init];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{for (int i=0; i<100000; i++) {aModel=[models objectAtIndex:0];NSString *sql=[NSString stringWithFormat:@"insert into notices values('%lf','%d','%@','%@','%@','%d','%d','%d','%d','%@')",aModel.myID,aModel.news_id,aModel.news_title,aModel.content,aModel.pic,aModel.sort,aModel.record_status,aModel.counter,aModel.suid,aModel.publish_time];[sqls addObject:sql];}int r1=[self open];[self beginService];int rc;int i;for (i=0; i<100000; i++) {rc=sqlite3_exec(database, [[sqls objectAtIndex:i] UTF8String], NULL, NULL, &errmsg);}[self commitService];[self close];if (i ==100000) {dispatch_async(dispatch_get_main_queue(), ^{NSLog(@"call back, the data is: %@", i);});} else {NSLog(@"error when download:%@", error);}});return 0;}
有關iOS中SQLite使用教程小編就給大家介紹這麼多,希望對大家有所協助!