iOS開發(fā)之輕量級數(shù)據(jù)庫SQLite3(增刪改查)

很多時候我們在做App的時候,需要對一些數(shù)據(jù)做緩存,在沒網(wǎng)絡(luò)支持的情況下給用戶展示一些效果症昏,這樣的需求在iOS開發(fā)中是非常常見的,qpple給我們提供了一個非常好用的數(shù)據(jù)庫:SQLite,它是一個輕量級關(guān)系數(shù)據(jù)庫,最初的設(shè)計目標(biāo)是用于嵌入式系統(tǒng),它占用資源非常少.在iOS中,只需要加入li’blibsqlite3.0依賴以及引入sqlite3.h頭文件即可.
SQLite是無類型的數(shù)據(jù)庫,可以保存任何類型的數(shù)據(jù),對于SQLite來說對字段不指定類型是完全有效的,學(xué)過數(shù)據(jù)庫的人都知道赠橙,存儲在數(shù)據(jù)庫中的每一條數(shù)據(jù)都必須要有PrimaryKey,這里設(shè)計到一個非常重要的概念:主鍵
數(shù)據(jù)表中每一條記錄都有一個主鍵,這就像我們的身份證號碼一樣,反過來說每一個主鍵對應(yīng)著一條數(shù)據(jù)記錄,所以,主鍵必須是唯一的,一般情況主鍵同時也是一個索引,所以通過主鍵查找記錄速度比較快,在關(guān)系類型庫中,一個表的主鍵可以作為另外一個表的外鍵,這樣,這兩個表之間就通過這個鍵建立了關(guān)系,主鍵一般是整數(shù)或者字符串,只要保證唯一就行,在SQLite中,主鍵如果是整型類型,該列的值可以自動增長,
所有的操作都是通過sql語句來進行操作的婶希,包括建表、數(shù)據(jù)的增刪差改蛆封、表關(guān)聯(lián)等等,至于sql語句在這里就不做介紹了,這里我們簡單的實現(xiàn)一下存儲數(shù)據(jù)并進行增刪查改操作勾栗,廢話不多說惨篱,看代碼:

- (void)sqliteAction {
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *dbPath =  [documentPath stringByAppendingPathComponent:@"student.sqlite"];
    
    int result =sqlite3_open([dbPath UTF8String], &_dataBase);
    if (result == SQLITE_OK) {
        NSLog(@"數(shù)據(jù)庫打開成功!");
        //創(chuàng)建表
        char *ERROR = NULL;
        //建表
        NSString *sqlStr = @"create table if not exists 'student' ('number' integer primary key autoincrement not null,'name' text,'sex' text,'age' integer)";
        if (sqlite3_exec(_dataBase, [sqlStr UTF8String], NULL, NULL, &ERROR) == SQLITE_OK) {
            NSLog(@"創(chuàng)建表成功!");
            //插入
            for (int i = 0; i< 100; i ++) {
                NSString *sqlStr =[NSString stringWithFormat:@"INSERT OR REPLACE INTO student(name,sex,age) VALUES('%@','%@','%d')",[NSString stringWithFormat:@"Chan%d",i],
                                   i %2 == 0 ? @"男":@"女",
                                   100 +i];
                if (sqlite3_exec(_dataBase, [sqlStr UTF8String], NULL, NULL, &ERROR) == SQLITE_OK) {
                    NSLog(@"插入成功!");
                }
            }
            
            //查詢
            NSString *selectStr = @"SELECT * FROM student";
            sqlite3_stmt *stmt;
            if (sqlite3_prepare(_dataBase, [selectStr UTF8String], -1, &stmt, nil) == SQLITE_OK) {
                while (sqlite3_step(stmt) == SQLITE_ROW ) {
                    NSString *name = [NSString stringWithUTF8String:(char*) sqlite3_column_text(stmt, 1)];
                    NSLog(@"name:%@",name);
                    
                    NSString *sex = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 2)];
                    NSLog(@"sex:%@",sex);
                    
                    NSInteger age = sqlite3_column_int(stmt, 3);
                    NSLog(@"%zd",age);
                   /* StudentModel  *model = [StudentModel new];
                    model.name = name;
                    model.sex = sex;
                    model.age = age;
                    [_dataArray addObject: model];*/
                }
                if (sqlite3_step(stmt) == SQLITE_DONE) {
                    //釋放句柄
                    sqlite3_finalize(stmt);
                }
            }
        } else {
            NSLog(@"創(chuàng)建表失敗!");
        }
    } else {
        NSLog(@"數(shù)據(jù)庫打開失敗!");
        sqlite3_close(_dataBase);
    }
}



- (void)openSqlite {
    //判斷數(shù)據(jù)庫是否為空,如果不為空說明已經(jīng)打開
    if(_dataBase != nil) {
        NSLog(@"數(shù)據(jù)庫已經(jīng)打開");
        return;
    }
    //獲取文件路徑
    NSString *str = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *strPath = [str stringByAppendingPathComponent:@"my.sqlite"];
    NSLog(@"%@",strPath);
    //打開數(shù)據(jù)庫
    //如果數(shù)據(jù)庫存在就打開,如果不存在就創(chuàng)建一個再打開
    int result = sqlite3_open([strPath UTF8String], &_dataBase);
    //判斷
    if (result == SQLITE_OK) {
        NSLog(@"數(shù)據(jù)庫打開成功");
    } else {
        NSLog(@"數(shù)據(jù)庫打開失敗");
    }
}


- (void)createTable {
    NSString *sqlite = [NSString stringWithFormat:@"create table if not exists 'student' ('number' integer primary key autoincrement not null,'name' text,'sex' text,'age'integer)"];
    char *error = NULL;//執(zhí)行sqlite語句失敗的時候,會把失敗的原因存儲到里面
    int result = sqlite3_exec(_dataBase, [sqlite UTF8String], nil, nil, &error);
    if (result == SQLITE_OK) {
        NSLog(@"創(chuàng)建表成功");
    } else {
        NSLog(@"創(chuàng)建表失敗");
    }
}

//添加數(shù)據(jù)
- (void)addStudent:(Student *)stu {
    NSString *sqlite = [NSString stringWithFormat:@"insert into student(number,name,age,sex) values ('%ld','%@','%@','%ld')",stu.number,stu.name,stu.sex,stu.age];
    char *error = NULL;//執(zhí)行sqlite語句失敗的時候,會把失敗的原因存儲到里面
    int result = sqlite3_exec(_dataBase, [sqlite UTF8String], nil, nil, &error);
    if (result == SQLITE_OK) {
        NSLog(@"添加數(shù)據(jù)成功");
    } else {
        NSLog(@"添加數(shù)據(jù)失敗");
    }
}

//刪除數(shù)據(jù)
- (void)delete:(Student*)stu {
    //1.準備sqlite語句
    NSString *sqlite = [NSString stringWithFormat:@"delete from student where number = '%ld'",stu.number];
    //2.執(zhí)行sqlite語句
    char *error = NULL;//執(zhí)行sqlite語句失敗的時候,會把失敗的原因存儲到里面
    int result = sqlite3_exec(_dataBase, [sqlite UTF8String], nil, nil, &error);
    if (result == SQLITE_OK) {
        NSLog(@"刪除數(shù)據(jù)成功");
    } else {
        NSLog(@"刪除數(shù)據(jù)失敗%s",error);
    }
}

//修改數(shù)據(jù)
- (void)updataWithStu:(Student *)stu {
    //1.sqlite語句
    NSString *sqlite = [NSString stringWithFormat:@"update student set name = '%@',sex = '%@',age = '%ld' where number = '%ld'",stu.name,stu.sex,stu.age,stu.number];
    //2.執(zhí)行sqlite語句
    char *error = NULL;//執(zhí)行sqlite語句失敗的時候,會把失敗的原因存儲到里面
    int result = sqlite3_exec(_dataBase, [sqlite UTF8String], nil, nil, &error);
    if (result == SQLITE_OK) {
        NSLog(@"修改數(shù)據(jù)成功");
    } else {
        NSLog(@"修改數(shù)據(jù)失敗");
    }
}

//查詢所有數(shù)據(jù)
- (NSMutableArray*)selectWithStu {
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSString *sqlite = [NSString stringWithFormat:@"select * from student"];
    sqlite3_stmt *stmt = NULL;
    int result = sqlite3_prepare(_dataBase, sqlite.UTF8String, -1, &stmt, NULL);//第4個參數(shù)是一次性返回所有的參數(shù),就用-1
    if (result == SQLITE_OK) {
        NSLog(@"查詢成功");
        //4.執(zhí)行n次
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            Student *stu = [[Student alloc] init];
            //從伴隨指針獲取數(shù)據(jù),第0列
            stu.number = sqlite3_column_int(stmt, 0);
            //從伴隨指針獲取數(shù)據(jù),第1列
            stu.name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 1)] ;
            //從伴隨指針獲取數(shù)據(jù),第2列
            stu.sex = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 2)] ;
            //從伴隨指針獲取數(shù)據(jù),第3列
            stu.age = sqlite3_column_int(stmt, 3);
        }
    } else {
        NSLog(@"查詢失敗");
    }
    sqlite3_finalize(stmt);
    return array;
}

- (void)closeSqlite {
    if (sqlite3_close(_dataBase) == SQLITE_OK) {
        NSLog(@"數(shù)據(jù)庫關(guān)閉成功");
    } else {
        NSLog(@"數(shù)據(jù)庫關(guān)閉失敗");
    }
}

運行完成之后围俘,我們可以在沙盒文件系統(tǒng)里面看到創(chuàng)建的數(shù)據(jù)庫文件:


sqlite.png
sqlite Query.png

我們可以使用sqlite工具打開這個student.sqlite數(shù)據(jù)庫文件查看表結(jié)構(gòu):


SQLite_table.png

表中的數(shù)據(jù):


SQLite_data.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砸讳,一起剝皮案震驚了整個濱河市琢融,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌簿寂,老刑警劉巖漾抬,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陶耍,居然都是意外死亡奋蔚,警方通過查閱死者的電腦和手機她混,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門烈钞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坤按,你說我怎么就攤上這事毯欣。” “怎么了臭脓?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵酗钞,是天一觀的道長。 經(jīng)常有香客問我来累,道長砚作,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任嘹锁,我火速辦了婚禮葫录,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘领猾。我一直安慰自己米同,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布摔竿。 她就那樣靜靜地躺著面粮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪继低。 梳的紋絲不亂的頭發(fā)上熬苍,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機與錄音袁翁,去河邊找鬼柴底。 笑死,一個胖子當(dāng)著我的面吹牛梦裂,可吹牛的內(nèi)容都是我干的似枕。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼年柠,長吁一口氣:“原來是場噩夢啊……” “哼凿歼!你這毒婦竟也來了褪迟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤答憔,失蹤者是張志新(化名)和其女友劉穎味赃,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虐拓,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡心俗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓉驹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片城榛。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖态兴,靈堂內(nèi)的尸體忽然破棺而出狠持,到底是詐尸還是另有隱情,我是刑警寧澤瞻润,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布喘垂,位于F島的核電站,受9級特大地震影響绍撞,放射性物質(zhì)發(fā)生泄漏正勒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一傻铣、第九天 我趴在偏房一處隱蔽的房頂上張望章贞。 院中可真熱鬧,春花似錦矾柜、人聲如沸阱驾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽里覆。三九已至,卻和暖如春缆瓣,著一層夾襖步出監(jiān)牢的瞬間喧枷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工弓坞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留隧甚,地道東北人。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓渡冻,卻偏偏與公主長得像戚扳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子族吻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容