一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

[原創(chuàng)] Xcode中使用sqlite3訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)

 永恒clek4xeu0r 2017-01-13

  最近開(kāi)始寫(xiě)博客了,把我學(xué)習(xí)到的東西進(jìn)行匯總和總結(jié),今天就說(shuō)說(shuō)怎么使用sqlite3來(lái)操縱數(shù)據(jù)庫(kù)吧   

  數(shù)據(jù)庫(kù)的相關(guān)知識(shí)我就不去說(shuō)明了,畢竟只要會(huì)sql語(yǔ)言的人就大家都一樣。

  本案例是在Xcode環(huán)境下創(chuàng)建的single view application進(jìn)行演示操作,如有不清楚的朋友可以找我下載代碼。qq:1750587828.

  首先第一點(diǎn),為什么要使用sqlite3?   

  在iOS的編程中,毫無(wú)疑問(wèn)接觸最多的就是界面的代碼編排和設(shè)計(jì),數(shù)據(jù)的解析與放置,算法的各種撓頭問(wèn)題。。。   在數(shù)據(jù)的解析與放置這一塊,就會(huì)涉及到數(shù)據(jù)庫(kù)緩存的操作,我們都知道,iOS手機(jī)編程是在手機(jī)端運(yùn)行的,你不能老是去服務(wù)器端讀取數(shù)據(jù)啊,好,就算你不煩,手機(jī)也跑的起來(lái),流量不要過(guò)啊,對(duì)于手機(jī)控或者應(yīng)用使用者來(lái)說(shuō),流量就是生命,而且,如果總是去服務(wù)器端讀取數(shù)據(jù),對(duì)手機(jī)的運(yùn)行速度也會(huì)有影響,畢竟有一個(gè)網(wǎng)絡(luò)傳輸?shù)倪^(guò)程,所以,為了讓用戶(hù)有一個(gè)更好的體驗(yàn),一般建議的做法是,將服務(wù)器的數(shù)據(jù)進(jìn)行下載,然后通過(guò)數(shù)據(jù)庫(kù)緩存起來(lái),這樣就不用每次每次的去請(qǐng)求服務(wù)器數(shù)據(jù)了,如果在數(shù)據(jù)庫(kù)中有的數(shù)據(jù),直接可以通過(guò)數(shù)據(jù)庫(kù)查詢(xún)得到,而省去了一次甚至多次的服務(wù)器請(qǐng)求操作。而sqlite3就是提供了一種C語(yǔ)言的訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的形式。之后我們的代碼會(huì)看到,其實(shí)sqlite3的語(yǔ)法可能比較難以理解,不過(guò),我也會(huì)給大家來(lái)進(jìn)行介紹的。      

  那么第二點(diǎn),使用sqlite3的好處是什么?

  使用sqlite3的好處么,除開(kāi)語(yǔ)法的各種蛋疼之外,訪(fǎng)問(wèn)的速度還是會(huì)比FMDB快一些的。而且,隨著一步步的匯總和總結(jié),你可以清晰的知道每一句sqlite3的語(yǔ)句的作用,而不是使用封裝好了的語(yǔ)句,只要用就可以了,但是不知道是為什么。我個(gè)人覺(jué)得,學(xué)習(xí)學(xué)習(xí)吧,還是要知其然,亦知其所以然這樣才能學(xué)的踏實(shí)。   

  第三點(diǎn),讓我們來(lái)開(kāi)始學(xué)習(xí)sqlite3的使用方式吧:  

  3.1 第一步,引入sqlite3庫(kù),并在使用sqlite3的地方導(dǎo)入sqlite3.

  3.2 第二步,創(chuàng)建sqlite數(shù)據(jù)庫(kù)文件   

  sqlite3提供的是一種訪(fǎng)問(wèn)操縱數(shù)據(jù)庫(kù)的形式,那么,如果想要使用sqlite3來(lái)訪(fǎng)問(wèn)操縱數(shù)據(jù)庫(kù),首先我們得先有個(gè)數(shù)據(jù)庫(kù),下面就是一句代碼生成一個(gè)數(shù)據(jù)庫(kù)文件。

/*得到數(shù)據(jù)庫(kù)文件地址,這是一個(gè)拼接的地址字符串,是沙盒路徑下面的shop.sqlite文件,

這個(gè)文件名可以隨便取名字,后綴最好是db啊或者sqlite這種,用來(lái)表示這是一個(gè)數(shù)據(jù)庫(kù)文件*/

NSString* filename=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@'shop.sqlite'];

/*sqlite3_open是我們接觸到的第一條sqlite3語(yǔ)句,它的作用時(shí)打開(kāi)數(shù)據(jù)庫(kù)連接,如果有數(shù)據(jù)庫(kù)文件就打開(kāi)它,沒(méi)有就重新創(chuàng)建數(shù)據(jù)庫(kù),這個(gè)方法有一個(gè)枚舉的返回值表示是否正常打開(kāi)了數(shù)據(jù)庫(kù),我用int的變量status去接收了這個(gè)值,后面會(huì)進(jìn)行判斷。

sqlite3_open有兩個(gè)參數(shù),第一個(gè)參數(shù)是數(shù)據(jù)庫(kù)文件的路徑,第二個(gè)參數(shù)是一個(gè)數(shù)據(jù)庫(kù)的引用,即一個(gè)sqlite3*類(lèi)型的引用;

filename.UTF8String:filename本身是oc的字符串類(lèi)型,但是sqlite3_open要求傳遞的是C類(lèi)型的字符串,所以,使用UTF8String將oc的字符串類(lèi)型轉(zhuǎn)換為C類(lèi)型的字符串

*/

int status=sqlite3_open(filename.UTF8String, &_shop);

    if(status == SQLITE_OK)//枚舉值SQLITE_OK,代表成功的狀態(tài)

    {

NSLog(@'打開(kāi)數(shù)據(jù)庫(kù)成功');

  }

    else

           NSLog(@'打開(kāi)數(shù)據(jù)庫(kù)失敗');

  3.3 創(chuàng)建數(shù)據(jù)庫(kù)表

  當(dāng)我們打開(kāi)了數(shù)據(jù)庫(kù)連接的時(shí)候,表示在程序的沙盒路徑下已經(jīng)創(chuàng)建了一個(gè)shop.sqlite的數(shù)據(jù)庫(kù)文件,而這個(gè)數(shù)據(jù)庫(kù)里現(xiàn)在什么東西都沒(méi)有,我們需要?jiǎng)?chuàng)建一張數(shù)據(jù)庫(kù)表來(lái)存放數(shù)據(jù)。在這里我就封裝一個(gè)setupTable來(lái)進(jìn)行創(chuàng)建表的操作。

-(void) setupTable
{

//創(chuàng)表語(yǔ)句,IF NOT EXISTS防止創(chuàng)建重復(fù)的表,AUTOINCREMENT是自動(dòng)增長(zhǎng)關(guān)鍵字,real是數(shù)字類(lèi)型

const
char
* sql='CREATE TABLE IF NOT EXISTS t_shop(id integer PRIMARY KEY AUTOINCREMENT,name text NOT NULL,price real);';

//保存錯(cuò)誤信息的變量

char * errMsg=NULL;

/*sqlite3_exec是我們接觸到的第二個(gè)sqlite3語(yǔ)句,這個(gè)語(yǔ)句用于執(zhí)行除了查詢(xún)語(yǔ)句以外的其他語(yǔ)句.

    它有一個(gè)枚舉類(lèi)型的返回值,和sqlite3_open返回的枚舉值一致,這里我并沒(méi)有使用變量保存,因?yàn)槲矣衅渌问絹?lái)獲得創(chuàng)建表是否成功。

    sqlite3_exec需要傳遞5個(gè)參數(shù),第一個(gè)參數(shù)是數(shù)據(jù)庫(kù)引用即sqlite3* _shop,第二個(gè)參數(shù)是要執(zhí)行的sql語(yǔ)句,

    第三個(gè)參數(shù)是執(zhí)行完sql語(yǔ)句后要執(zhí)行的函數(shù),第四個(gè)參數(shù)是執(zhí)行完sql語(yǔ)句后要執(zhí)行的函數(shù)的參數(shù),第五個(gè)參數(shù)是執(zhí)行完sql語(yǔ)句后的報(bào)錯(cuò)信息。

  */

sqlite3_exec(_shop, sql, NULL, NULL, &errMsg);

if(errMsg)//如果存在報(bào)錯(cuò)信息,代表語(yǔ)句執(zhí)行失敗,比判斷枚舉值要更簡(jiǎn)單一些

        {

NSLog(@'創(chuàng)建表shop失敗-%s',errMsg);//打印錯(cuò)誤信息

        }

}

  3.4 封裝數(shù)據(jù)庫(kù)連接和創(chuàng)建數(shù)據(jù)庫(kù)表

-(void)setupDB

{

//得到數(shù)據(jù)庫(kù)文件地址

NSString* filename=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@'shop.sqlite'];

//NSLog(@'%@',filename);

//打開(kāi)數(shù)據(jù)庫(kù)連接,如果有就打開(kāi),沒(méi)有就重新創(chuàng)建連接

int status=sqlite3_open(filename.UTF8String, &_shop);

if(status == SQLITE_OK)

    {

NSLog(@'打開(kāi)數(shù)據(jù)庫(kù)成功');

//創(chuàng)表語(yǔ)句

        [selfsetupTable];

    }

else

    {

NSLog(@'打開(kāi)數(shù)據(jù)庫(kù)失敗');

    }

}

  3.5 數(shù)據(jù)表操縱

  所謂的數(shù)據(jù)表操縱即是對(duì)數(shù)據(jù)表中數(shù)據(jù)的增刪改,也是最經(jīng)常會(huì)使用到的功能。即執(zhí)行insert,update,delete語(yǔ)句。

- (IBAction)add:(id)sender {//這里是一個(gè)按鈕的點(diǎn)擊提供的新增功能

/*拼接插入數(shù)據(jù)的sql語(yǔ)句*/

NSString * sql=[NSStringstringWithFormat:@'INSERT INTO t_shop(name,price) VALUES('%@',%f)',self.name.text,self.price.text.doubleValue];

char* errMsg=NULL;

sqlite3_exec(self.shop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

    {

NSLog(@'插入數(shù)據(jù)失敗--%s',errMsg);

    }

}

-(void)updateData//這里是一個(gè)方法提供了更新功能

{

//拼接sql更新語(yǔ)句

NSString * sql=[NSStringstringWithFormat:@'update t_shop set name='%@',price='%@' where id=%@',self.name.text,self.price.text,self.lbl.text];

    //NSLog(@'%@',sql);

char* errMsg=NULL;

sqlite3_exec(self.myShop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

    {

NSLog(@'更新數(shù)據(jù)失敗--%s',errMsg);

    }

}

-(void)deleteDataById:(int)pid

{//提供一個(gè)方法執(zhí)行刪除操作,該方法要求得到要?jiǎng)h除的數(shù)據(jù)的id

  //拼接sql刪除語(yǔ)句

NSString * sql=[NSStringstringWithFormat:@'DELETE FROM t_shop where id=%d',pid];

char* errMsg=NULL;

sqlite3_exec(self.shop, sql.UTF8String, NULL, NULL, &errMsg);

if(errMsg)

    {

NSLog(@'刪除數(shù)據(jù)失敗--%s',errMsg);

    }

}

  大家可以觀(guān)察上面的三個(gè)方法,會(huì)發(fā)現(xiàn)除了sql語(yǔ)句的拼接不一樣以外,其他的地方幾乎一模一樣,所以,增刪改的操作相對(duì)來(lái)說(shuō)還是比較簡(jiǎn)單的。

  3.6 查詢(xún)數(shù)據(jù) 

/**

 *  查詢(xún)數(shù)據(jù)

 */

-(void)setupData

{

constchar * sql='select * from t_shop';//查詢(xún)sql語(yǔ)句

//stmt用來(lái)取出查詢(xún)結(jié)果

sqlite3_stmt *stmt=NULL;

/*sqlite3_prepare_v2函數(shù)是準(zhǔn)備要執(zhí)行sql查詢(xún)的一個(gè)函數(shù),可以當(dāng)做這個(gè)函數(shù)就是用來(lái)做sql查詢(xún)之前的準(zhǔn)備工作的,

  它也是返回一個(gè)枚舉作為準(zhǔn)備工作的結(jié)果,SQLITE_OK則代表準(zhǔn)備工作ok

  sqlite3_prepare_v2需要傳入5個(gè)參數(shù),第一個(gè)參數(shù)是數(shù)據(jù)庫(kù)引用即(sqlite3* _shop),第二個(gè)參數(shù)是要執(zhí)行的sql語(yǔ)句,第三個(gè)參數(shù)是sql語(yǔ)句的長(zhǎng)度

  第四個(gè)參數(shù)是查詢(xún)結(jié)果stmt的引用,查詢(xún)完成后,查詢(xún)結(jié)果將會(huì)存入該引用,第五個(gè)參數(shù)是指向無(wú)法使用的部分的指針,一般不會(huì)用到,給NULL就可以了

  */

int status = sqlite3_prepare_v2(_shop, sql, -1, &stmt, NULL);

if(status == SQLITE_OK)//準(zhǔn)備成功,SQL語(yǔ)句正確

    {

/*sqlite3_step(stmt)函數(shù)將會(huì)執(zhí)行查詢(xún)并且將查詢(xún)到的當(dāng)前記錄存入到stmt(sqlite3_stmt * 類(lèi)型)中

    第一次執(zhí)行sqlite3_step(stmt)將會(huì)將表中的第一條數(shù)據(jù)存入到stmt中,第二次執(zhí)行sqlite3_step(stmt)將會(huì)把表中的第二條記錄存入到stmt中

  也就是說(shuō),while(sqlite3_step(stmt)==SQLITE_ROW)將會(huì)一條一條的去讀取表中的記錄,而SQLITE_ROW枚舉判斷的是有讀取到數(shù)據(jù)行的情況*/

while(sqlite3_step(stmt) == SQLITE_ROW)//成功指向一條記錄

        {

Shop* shop=[[Shopalloc]init];//封裝的實(shí)體

/*sqlite3_column_xxxx函數(shù):它用來(lái)讀取數(shù)據(jù)行中不同類(lèi)型的數(shù)據(jù),該函數(shù)的返回值就是讀取到得數(shù)據(jù)內(nèi)容,

      該函數(shù)需要2個(gè)參數(shù),第一個(gè)參數(shù)是存放數(shù)據(jù)的stmt,第二個(gè)參數(shù)是數(shù)據(jù)列下標(biāo)*/

            shop.pid= sqlite3_column_int(stmt, 0);//讀取stmt中存儲(chǔ)的第0列數(shù)據(jù)

constchar* pname= (constchar*)sqlite3_column_text(stmt, 1);//讀取stmt中存儲(chǔ)的第1列數(shù)據(jù)

constchar* pprice = (constchar*)sqlite3_column_text(stmt, 2);//讀取stmt中存儲(chǔ)的第2列數(shù)據(jù)

            shop.name = [NSStringstringWithUTF8String:pname];//將C類(lèi)型的字符串轉(zhuǎn)換為oc類(lèi)型的字符串并存儲(chǔ)

            shop.price = [NSStringstringWithUTF8String:pprice];//將C類(lèi)型的字符串轉(zhuǎn)換為oc類(lèi)型的字符串并存儲(chǔ)

//NSLog(@'編號(hào):%d,商品名:%s,價(jià)格:%s',shop.pid,pname,pprice);

        }

    }

}

  那么,寫(xiě)到這里,相信大家對(duì)sqlite3的基本使用已經(jīng)有了大致的了解,如果對(duì)代碼中有不理解的地方,或者有其他相關(guān)的問(wèn)題,可以找我一起來(lái)研究討論。

  第一次發(fā)博客,希望大家提出寶貴的意見(jiàn)和建議,編程路上,與你同行。

分類(lèi): Object-C

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    亚洲最新中文字幕一区| 91午夜少妇极品福利| 九九热精品视频在线观看| 91精品欧美综合在ⅹ| 熟女少妇一区二区三区蜜桃| 日韩精品免费一区三区| 老司机精品在线你懂的| 国产av一区二区三区四区五区| 欧美一区二区在线日韩| 欧美日韩一级黄片免费观看| 日本99精品在线观看| 色欧美一区二区三区在线| 国产欧美日产久久婷婷| 亚洲国产丝袜一区二区三区四| 偷自拍亚洲欧美一区二页| 亚洲永久一区二区三区在线| 亚洲日本中文字幕视频在线观看| 熟女乱一区二区三区四区| 99久久精品久久免费| 99久久精品午夜一区二区| 国产亚洲欧美日韩国亚语| 国产av一区二区三区久久不卡| 欧美午夜性刺激在线观看| 日韩中文字幕人妻精品| 国产一区二区不卡在线播放| 熟女高潮一区二区三区| 久久精品蜜桃一区二区av| 亚洲国产天堂av成人在线播放| 人人爽夜夜爽夜夜爽精品视频| 亚洲人妻av中文字幕| 国产目拍亚洲精品区一区| 免费性欧美重口味黄色| 黄片在线免费看日韩欧美| 欧美日韩校园春色激情偷拍| 91麻豆精品欧美视频| 久久99这里只精品热在线| 亚洲天堂一区在线播放| 日韩欧美三级中文字幕| 人人妻在人人看人人澡| 97人妻精品免费一区二区| 亚洲精品国产精品日韩|