IOS數(shù)據(jù)庫

創(chuàng)建數(shù)據(jù)庫過程需要3個步驟:

1、使用sqlite3_open函數(shù)打開數(shù)據(jù)庫;

2、使用sqlite3_exec函數(shù)執(zhí)行Create?Table語句,創(chuàng)建數(shù)據(jù)庫表;

3、使用sqlite3_close函數(shù)釋放資源。

這個過程中使用了3個SQLite3函數(shù),它們都是純C語言函數(shù),通過Objective-C去調(diào)用C函數(shù)當然不是什么問題,但是也要注意Objective-C數(shù)據(jù)類型與C數(shù)據(jù)類型兼容性問題。

下 面我們使用SQLite技術(shù)實現(xiàn)備忘錄案例,與屬性列表文件實現(xiàn)一樣,我們只需要修改持久層工程(PersistenceLayer)中NoteDAO類 就可以了。首先我們需要添加SQLite3庫到工程環(huán)境中,有3個工程需要添加到哪個呢?應(yīng)該添加到可以運行的工程即表示層工程 PresentationLayer。選擇工程PresentationLayer中 TARGETS→PresentationLayer→Link?Binary?With?Libraries,點擊左下角的“+”,彈出對話框選擇 libsqlite3.dylib或libsqlite3.0.dylib,在彈出的對話框中點擊Add添加。NoteDAO.h文件的修改:

Cpp代碼

#import?”Note.h”

#import?”sqlite3.h”

#define?DBFILE_NAME?@”NotesList.sqlite3″

@interface?NoteDAO?:?NSObject

{

sqlite3?*db;

}

+?(NoteDAO*)sharedManager;

-?(NSString?*)applicationDocumentsDirectoryFile;

-?(void)createEditableCopyOfDatabaseIfNeeded;

//插入Note方法

-(int)?create:(Note*)model;

//刪除Note方法

-(int)?remove:(Note*)model;

//修改Note方法

-(int)?modify:(Note*)model;

//查詢所有數(shù)據(jù)方法

-(NSMutableArray*)?findAll;

//按照主鍵查詢數(shù)據(jù)方法

-(Note*)?findById:(Note*)model;

@end

我們需要使用語句#import?”sqlite3.h”引入sqlite3頭文件,而且需要定義sqlite3*成員變量db。NoteDAO.m中的createEditableCopyOfDatabaseIfNeeded方法:

Cpp代碼

-?(void)createEditableCopyOfDatabaseIfNeeded?{

NSString?*writableDBPath?=?[self?applicationDocumentsDirectoryFile];

if(sqlite3_open([writableDBPath?UTF8String],?&db)?!=?SQLITE_OK)?{?①

sqlite3_close(db);??②

NSAssert(NO,@”數(shù)據(jù)庫打開失敗?!?;

}else{

char*err;

NSString?*createSQL?=?[NSString?stringWithFormat:@"CREATE?TABLE?IF?NOT?EXISTS?Note

(cdate?TEXT?PRIMARY?KEY,?content?TEXT);"];?③

if(sqlite3_exec(db,[createSQL?UTF8String],NULL,NULL,&err)?!=?SQLITE_OK)?{?④

sqlite3_close(db);?⑤

NSAssert1(NO,?@”建表失敗,?%s”,?err);??⑥

}

sqlite3_close(db);??⑦

}

}

createEditableCopyOfDatabaseIfNeeded方法用于創(chuàng)建數(shù)據(jù)庫,第1步打開數(shù)據(jù) 庫,代碼①行,語句是 sqlite3_open([writableDBPath?UTF8String],?&db),sqlite3_open函數(shù)的第1個參數(shù)是 數(shù)據(jù)庫文件完整的路徑,但是需要注意的是在SQLite3函數(shù)中接受的是char*的UTF-8類型數(shù)據(jù),需要將NSString*轉(zhuǎn)換為UTF-8,使 用NSString*的UTF8String方法可以轉(zhuǎn)換,sqlite3_open函數(shù)第2個參數(shù)sqlite3指針變量db的地址。該函數(shù)的返回值是 int類型,在SQLite3中定義了很多常量,返回值等于常量SQLITE_OK則說明操作成功。

第2步執(zhí)行建表語句,代碼第④行,語句 sqlite3_exec(db,[createSQL?UTF8String],NULL,NULL,&err)執(zhí)行建表的SQL。第1個參數(shù) 是sqlite3指針變量db的地址,第2個參數(shù)是要執(zhí)行的sql語句,第3個參數(shù)是要回調(diào)函數(shù),第4個參數(shù)是要回調(diào)函數(shù)的參數(shù),第5個參數(shù)是執(zhí)行出錯的 字符串。建表SQL語句是,如果表Note存在這不用創(chuàng)建。

CREATE?TABLE?IF?NOT?EXISTS?Note?(cdate?TEXT?PRIMARY?KEY,?content?TEXT)

第3步使用sqlite3_close函數(shù)釋放資源,代碼②、⑤、⑦行所示,在數(shù)據(jù)庫打開失敗、Create?Table執(zhí)行失敗和成功執(zhí)行完成時候調(diào)用。原則上無論正常結(jié)束還是異常結(jié)束必須使用sqlite3_close函數(shù)釋放資源。

查詢數(shù)據(jù)

數(shù)據(jù)查詢一般會帶有查詢條件,這個使用SQL語句where子句很容易實現(xiàn),但是在程序中需要動態(tài)綁定參數(shù)給where子句。執(zhí)行查詢數(shù)據(jù)步驟如下:

1、使用sqlite3_open函數(shù)打開數(shù)據(jù)庫;

2、使用sqlite3_prepare_v2函數(shù)預(yù)處理SQL語句;

3、使用sqlite3_bind_text函數(shù)綁定參數(shù);

4、使用sqlite3_step函數(shù)執(zhí)行SQL語句,遍歷結(jié)果集;

5、使用sqlite3_column_text等函數(shù)提取字段數(shù)據(jù);

6、使用sqlite3_finalize和sqlite3_close函數(shù)釋放資源。

NoteDAO.m中的按照主鍵查詢數(shù)據(jù)方法:

Cpp代碼

-(Note*)?findById:(Note*)model

{

NSString?*path?=?[self?applicationDocumentsDirectoryFile];

if(sqlite3_open([path?UTF8String],?&db)?!=?SQLITE_OK)?{?①

sqlite3_close(db);??②

NSAssert(NO,@”數(shù)據(jù)庫打開失敗?!?;

}else{

NSString?*qsql?=?@”SELECT?cdate,content?FROM?Note?where?cdate?=?”;

sqlite3_stmt?*statement;

//預(yù)處理過程

if(sqlite3_prepare_v2(db,?[qsql?UTF8String],?-1,?&statement,?NULL)?==?SQLITE_OK)?{?③

//準備參數(shù)

NSDateFormatter?*dateFormatter?=?[[NSDateFormatter?alloc]?init];?④

[dateFormatter?setDateFormat:@"yyyy-MM-dd?HH:mm:ss"];

NSString?*nsdate?=?[dateFormatter?stringFromDate:model.date];

//綁定參數(shù)開始

sqlite3_bind_text(statement,?1,?[nsdate?UTF8String],?-1,?NULL);?⑤

//執(zhí)行

if(sqlite3_step(statement)?==?SQLITE_ROW)?{?⑥

char*cdate?=?(char*)?sqlite3_column_text(statement,?0);?⑦

NSString?*nscdate?=?[[NSString?alloc]?initWithUTF8String:?cdate];

char*content?=?(char*)?sqlite3_column_text(statement,?1);

NSString?*?nscontent?=?[[NSString?alloc]?initWithUTF8String:?content];

Note*?note?=?[[Note?alloc]?init];

note.date?=?[dateFormatter?dateFromString:nscdate];

note.content?=?nscontent;

sqlite3_finalize(statement);

sqlite3_close(db);

returnnote;

}

}

sqlite3_finalize(statement);?⑧

sqlite3_close(db);??⑨

}

returnnil;

}

該方法執(zhí)行了6個步驟,其中第1個步驟,代碼第①行所示,它與創(chuàng)建數(shù)庫的第1個步驟是一樣的,不用再介紹了。

第 2個步驟,代碼第③行所示,語句 sqlite3_prepare_v2(db,?[qsql?UTF8String],?-1,?&statement,?NULL)是預(yù)處理 SQL語句,預(yù)處理目的是將SQL編譯成二進制代碼,提高SQL語句執(zhí)行的速度。sqlite3_prepare_v2函數(shù)的第3個參數(shù)-1代表全部 sql字符串長度,第4個參數(shù)&statement是sqlite3_stmt指針的地址,它是語句對象,通過語句對象可以執(zhí)行SQL語句,第5 個參數(shù)是sql語句沒有被執(zhí)行的部分語句。

第3個步驟,代碼第⑤行所示,語句sqlite3_bind_text(statement,?1,?[nsdate?UTF8String],?-1,?NULL)是綁定SQL語句參數(shù)。在SQL語句中帶有問號,這個問號就是要綁定的參數(shù),問號是占位符。

NSString?*qsql?=?@”SELECT?cdate,content?FROM?Note?where?cdate?=?”;

sqlite3_bind_text函數(shù)是綁定參數(shù),第1個參數(shù)是statement指針,第2個參數(shù)為序號(從1開始),第3個參數(shù)為字符串值,第4個參數(shù)為字符串長度,第5個參數(shù)為一個函數(shù)指針。

第4個步驟sqlite3_step(statement)執(zhí)行SQL語句,代碼第⑥行所示,sqlite3_step返回int類型,等于SQLITE_ROW說明還要其它的行沒有遍歷。

第 5個步驟提取字段數(shù)據(jù),代碼第⑦行所示,使用sqlite3_column_text(statement,?0)函數(shù)可以讀取字符串類型字段,第2參數(shù) 是指定select字段的索引(從0開始)。同樣char*轉(zhuǎn)換成為NSString*類型,需要initWithUTF8String:構(gòu)造方法。讀取 字段函數(shù)采用與字段類型有關(guān)系,SQLite3的類似的常用函數(shù)還有:

sqlite3_column_blob()

sqlite3_column_double()

sqlite3_column_int()

sqlite3_column_int64()

sqlite3_column_text()

sqlite3_column_text16()

關(guān)于其它的API可以參考http://www.sqlite.org/cintro.html。

第6個步驟是釋放資源,創(chuàng)建數(shù)據(jù)庫過程不同,除了使用sqlite3_close函數(shù)關(guān)閉數(shù)據(jù)庫,代碼第⑧行所示,還要使用sqlite3_finalize函數(shù)釋放語句對象statement代碼第⑨行所示。

NoteDAO.m中的查詢所有數(shù)據(jù)方法:

Cpp代碼

-(NSMutableArray*)?findAll

{

NSString?*path?=?[self?applicationDocumentsDirectoryFile];

NSMutableArray?*listData?=?[[NSMutableArray?alloc]?init];

if(sqlite3_open([path?UTF8String],?&db)?!=?SQLITE_OK)?{

sqlite3_close(db);

NSAssert(NO,@”數(shù)據(jù)庫打開失敗。”);

}else{

NSString?*qsql?=?@”SELECT?cdate,content?FROM?Note”;

sqlite3_stmt?*statement;

//預(yù)處理過程

if(sqlite3_prepare_v2(db,?[qsql?UTF8String],?-1,?&statement,?NULL)?==?SQLITE_OK)?{

NSDateFormatter?*dateFormatter?=?[[NSDateFormatter?alloc]?init];

[dateFormatter?setDateFormat:@"yyyy-MM-dd?HH:mm:ss"];

//執(zhí)行

while(sqlite3_step(statement)?==?SQLITE_ROW)?{

char*cdate?=?(char*)?sqlite3_column_text(statement,?0);

NSString?*nscdate?=?[[NSString?alloc]?initWithUTF8String:?cdate];

char*content?=?(char*)?sqlite3_column_text(statement,?1);

NSString?*?nscontent?=?[[NSString?alloc]?initWithUTF8String:?content];

Note*?note?=?[[Note?alloc]?init];

note.date?=?[dateFormatter?dateFromString:nscdate];

note.content?=?nscontent;

[listData?addObject:note];

}

}

sqlite3_finalize(statement);

sqlite3_close(db);

}

returnlistData;

}

查詢所有數(shù)據(jù)方法與按照主鍵查詢數(shù)據(jù)方法類似,區(qū)別在于本方法沒有查詢條件不需要綁定參數(shù)。遍歷的時候使用while循環(huán)語句,不是if語句。

while?(sqlite3_step(statement)?==?SQLITE_ROW)?{

…?…

}

修改數(shù)據(jù)

修改數(shù)據(jù)包括:insert、update和delete語句。這3個SQL語句都可以帶有參數(shù),關(guān)于參數(shù)的綁定與查詢where子句綁定的方式是一樣的。執(zhí)行修改數(shù)據(jù)步驟如下:

1、使用sqlite3_open函數(shù)打開數(shù)據(jù)庫;

2、使用sqlite3_prepare_v2函數(shù)預(yù)處理SQL語句;

3、使用sqlite3_bind_text函數(shù)綁定參數(shù);

4、使用sqlite3_step函數(shù)執(zhí)行SQL語句;

5、使用sqlite3_finalize和sqlite3_close函數(shù)釋放資源。

修改數(shù)據(jù)的步驟與查詢數(shù)據(jù)的步驟相比少了一個提取字段數(shù)據(jù)步驟。下面我們看看代碼部分。其它的步驟是一樣的。

NoteDAO.m中的插入Note方法:

Cpp代碼

-(int)?create:(Note*)model

{

NSString?*path?=?[self?applicationDocumentsDirectoryFile];

if(sqlite3_open([path?UTF8String],?&db)?!=?SQLITE_OK)?{?①

sqlite3_close(db);??②

NSAssert(NO,@”數(shù)據(jù)庫打開失敗?!?;

}else{

NSString?*sqlStr?=?@”INSERT?OR?REPLACE?INTO?note?(cdate,?content)?VALUES?(?,?)”;

sqlite3_stmt?*statement;

//預(yù)處理過程

if(sqlite3_prepare_v2(db,?[sqlStr?UTF8String],?-1,?&statement,?NULL)?==?SQLITE_OK)?{?③

NSDateFormatter?*dateFormatter?=?[[NSDateFormatter?alloc]?init];

[dateFormatter?setDateFormat:@"yyyy-MM-dd?HH:mm:ss"];

NSString?*nsdate?=?[dateFormatter?stringFromDate:model.date];

//綁定參數(shù)開始

sqlite3_bind_text(statement,?1,?[nsdate?UTF8String],?-1,?NULL);??④

sqlite3_bind_text(statement,?2,?[model.content?UTF8String],?-1,?NULL);

//執(zhí)行插入

if(sqlite3_step(statement)?!=?SQLITE_DONE)?{?⑤

NSAssert(NO,?@”插入數(shù)據(jù)失敗?!?;

}

}

sqlite3_finalize(statement);??⑥

sqlite3_close(db);??⑦

}

return0;

}

第⑤行代碼sqlite3_step(statement)語句執(zhí)行插入語句,常量SQLITE_DONE執(zhí)行完成。

NoteDAO.m中的刪除Note方法:

Cpp代碼

-(int)?remove:(Note*)model

{

NSString?*path?=?[self?applicationDocumentsDirectoryFile];

if(sqlite3_open([path?UTF8String],?&db)?!=?SQLITE_OK)?{

sqlite3_close(db);

NSAssert(NO,@”數(shù)據(jù)庫打開失敗。”);

}else{

NSString?*sqlStr?=?@”DELETE??from?note?where?cdate?=?”;

sqlite3_stmt?*statement;

//預(yù)處理過程

if(sqlite3_prepare_v2(db,?[sqlStr?UTF8String],?-1,?&statement,?NULL)?==?SQLITE_OK)?{

NSDateFormatter?*dateFormatter?=?[[NSDateFormatter?alloc]?init];

[dateFormatter?setDateFormat:@"yyyy-MM-dd?HH:mm:ss"];

NSString?*nsdate?=?[dateFormatter?stringFromDate:model.date];

//綁定參數(shù)開始

sqlite3_bind_text(statement,?1,?[nsdate?UTF8String],?-1,?NULL);

//執(zhí)行插入

if(sqlite3_step(statement)?!=?SQLITE_DONE)?{

NSAssert(NO,?@”刪除數(shù)據(jù)失敗。”);

}

}

sqlite3_finalize(statement);

sqlite3_close(db);

}

return0;

}

NoteDAO.m中的修改Note方法:

-(int)?modify:(Note*)model

{

NSString?*path?=?[self?applicationDocumentsDirectoryFile];

if(sqlite3_open([path?UTF8String],?&db)?!=?SQLITE_OK)?{

sqlite3_close(db);

NSAssert(NO,@”數(shù)據(jù)庫打開失敗?!?;

}else{

NSString?*sqlStr?=?@”UPDATE?note?set?content=??where?cdate?=?”;

sqlite3_stmt?*statement;

//預(yù)處理過程

if(sqlite3_prepare_v2(db,?[sqlStr?UTF8String],?-1,?&statement,?NULL)?==?SQLITE_OK)?{

NSDateFormatter?*dateFormatter?=?[[NSDateFormatter?alloc]?init];

[dateFormatter?setDateFormat:@"yyyy-MM-dd?HH:mm:ss"];

NSString?*nsdate?=?[dateFormatter?stringFromDate:model.date];

//綁定參數(shù)開始

sqlite3_bind_text(statement,?1,?[model.content?UTF8String],?-1,?NULL);

sqlite3_bind_text(statement,?2,?[nsdate?UTF8String],?-1,?NULL);

//執(zhí)行插入

if(sqlite3_step(statement)?!=?SQLITE_DONE)?{

NSAssert(NO,?@”修改數(shù)據(jù)失敗?!?;

}

}

sqlite3_finalize(statement);

sqlite3_close(db);

}

return0;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容