天天看點

iOS學習36資料處理之SQLite資料庫

1. 資料庫管理系統

 1> SQL語言概述

  SQL: SQL是Structured Query Language(結構化查詢語言)的縮寫。SQL是專為資料庫而建立的操作指令集, 是一種功能齊全的資料庫語言。

 2> 常見的資料庫

  MySQL: MySQL是一個精巧的SQL資料庫管理系統, 而且是開源的資料管理系統。MySQL 主要目标是快速、健壯和易用。 由于它的強大功能、靈活性、豐富的應用程式設計接口(API)以及精巧的系統結果,受到了廣大自由軟體愛好者甚至是商業軟體使用者的青睐。

  Oracle:Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關系資料庫管理系統。系統可移植性好、使用友善、功能強。

 3> 資料庫特征:

  • 以一定的方式存儲(表結構)
  • 能共享資料(很多人都能用)
  • 具有盡可能少的備援代碼(單表操作的代碼相對而言簡單,多表操作代碼比較複雜)
  • 與程式彼此獨立(與程式本身沒有太大的關系)

 4> 資料庫管理系統

  SQLite(http://www.sqlite.org/docs.html)是一個輕量級的關系資料庫。 SQLite最初的設計目标是用于嵌入式系統,它占用資源非常少,在嵌入式裝置中,隻需要幾百K的記憶體就夠了,目前應用于Android、iOS、Window Phone等智能手機。iOS使用時SQLite,隻需要加入libsqlite3.0.tbd依賴以及引入sqlite3.h頭檔案即可。

 5> 相關概念

  • 表:是資料庫中一個非常重要的對象,是其他對象的基礎。根據資訊分類情況,一個資料庫中可能包含若幹個資料表。
  • 字段:表的"列"稱為"字段",每個字段包含某一專題的資訊

  

  • 記錄:是指對應于資料表中一行資訊的一組完整的相關資訊。

2. SQL語句 

 1> SQLite資料庫資料類型

  SQLite是無類型的資料庫,可以儲存任何類型的資料,對于SQLite來說對字段不指定類型是完全有效的。(注:良好的程式設計習慣應該要為字段标注類型)

  為了使sqlite和其他資料庫間的相容性最大化,sqlite支援"類型近似"的觀點,列的類型近似指的是存儲在列上資料的推薦類型。

 2> SQLite近似類型規則

  • 如果類型字元串中包含"INT",那麼該字段的親緣類型為INTEGER。
  • 如果類型字元串中包含"CHAR"、"CLOB"或"TEXT",那麼該字段的親緣類型為TEXT,如VARCHAR。
  • 如果類型字元串中包含"BLOB",那麼該字段的親緣類型為NONE。
  • 如果類型字元串中包含"REAL"、"FLOA"或"DOUB",那麼該字段的親緣類型為REAL
  • 其餘情況下,字段的親緣類型為NUMERIC

 3> SQLite字段限制條件

  • not null(非空):

   在資料庫中允許除主鍵以為,其他的任何字段可以為空

  • unique(唯一):

   表示确定的,隻有這個沒有重複的

  • primary key(主鍵):

   不能為空(not null);

   不能重複(唯一unique);

   一個表裡可以沒有主鍵,但是如果設定完主鍵,必須遵守主鍵的特點(最好設定主鍵,友善我們查找相關資訊)

  • foreign key(外鍵):

   在MySQL裡面有聯表查詢,需要使用外鍵;

   作用: 可以根據外鍵查詢另一張表的某條具體資料

  • check 該字段資料用于必須滿足一定條件
  • default 該字段資料可以給定預設值
  • autoincrement(自增變量) 該字段資料如果為整型可以自動加 1

 4> SQL語句

  • 建表指令

  文法: creat table 表名(字段1 類型 限制1 限制2, 字段2 類型 限制1, ...); 

1 -- 需求:建立一個student表,表中字段有學号,姓名,年齡; 學号作為主鍵的限制條件,自增,不能為空; 姓名預設為'無名氏'; 年齡大于16
2 
3 create table if not exists student(s_id integer primary key autoincrement not null, s_name text default '無名氏', s_age integer check (s_age > 16));      
  • 資料插入指令

  文法: insert into 表名(字段1, 字段2, 字段3, ...) values(value1, value2, value3);

1 --事例:
2 insert into student(s_name, s_age) values('ff', 18);
3 insert into student(s_name, s_age) values('zf', 24);      
  • 資料更新指令

  文法: update 表名 set 字段名1 = 修改值1, 字段名2 = 修改值2 where 條件;

 1 update student set s_age = 18 where s_age = 24;                                              

  • 資料删除指令

  文法: delete from 表名 where 條件

 1 delete from student where s_age = 2;                                               

  • 資料查詢指令

  文法: select 要查找的字段 from 表名 where 條件;

1 -- * 表示所有的資料
2 select * from student;
3 select * from student where s_age = 18;
4 select s_name from student where s_age = 24;      

3. iOS的資料庫計數的實作 

 1> SQLite導入的架構

  • Xcode 6 中 libsqlite3.0.dylib
  • Xcode 7 中 libsqlite3.0.tdb

 2> 導入相應的架構步驟:

 3> 開始使用SQLite

  • 引入<sqlite3.h>頭檔案
  • 打開資料庫
  • 執行SQL指令(建表,增删查改)
  • 關閉資料庫

 4> SQLite文法

  • 建立或打開資料庫

   sqlite3_open() 将根據檔案路徑打開資料庫,如果不存在,則會建立一個新的資料庫。如果result 等于常量 SQLITE_OK,則表示成功打開資料庫。

   sqlite3 *db; db 一個打開的資料庫執行個體。

   資料庫檔案的路徑必須以 C語言字元串(而非NSString)傳入。

1    // 打開資料庫,很多地方都會使用到資料庫,是以初始化一個資料庫的靜态變量(句柄)
 2     static sqlite3 *db = nil; 
 3 
 4     // 打開資料庫,使用int去接收打開的結果
 5     // 第一個參數:self.dbPath代表資料庫的存儲路徑
 6     // 第二個參數:二級指針,資料庫的位址(句柄)
 7     
 8     int result = sqlite3_open([self.dbPath UTF8String], &db);
 9     
10     // result是一個枚舉值,有很多種情況
11     if (result == SQLITE_OK) {
12         NSLog(@"資料庫打開成功");
13     } else {
14         NSLog(@"資料庫打開失敗");
15     }      
  • 關閉資料庫:sqlite3_close(db);
1     int result = sqlite3_close(db);
2     
3     if (result == SQLITE_OK) {
4         NSLog(@"資料庫關閉成功");
5     } else {
6         NSLog(@"資料庫關閉失敗");
7     }      
  • 執行sql語句

  sqlite3_exec() 可以執行任何SQL語句,比如創表、更新、插入和删除操作。但是一般不用它執行查詢語句,因為它不會傳回查詢到的資料

  • 預執行

  方法使用及參數說明見代碼

   建立表

1     // 建立一個Person表,字段:uid integer類型主鍵 自增 不能為空,name text類型,gender text類型,age integer類型
 2     NSString *createStr = @"create table if not exists person(uid integer primary key autoincrement not null, name text, gender text, age integer)";
 3     /*
 4      int SQLITE_STDCALL sqlite3_exec(
 5         sqlite3*,
 6         const char *sql,
 7         int (*callback)(void*,int,char**,char**),
 8         void *,
 9         char **errmsg
10         );
11      */
12     
13     // 第一個參數:資料庫
14     // 第一個參數:sql語句,需要進行編碼
15     // 第一個參數:結果回調的一個函數
16     // 第一個參數:回調函數的一個參數
17     // 第一個參數:錯誤資訊
18     int result = sqlite3_exec(db, [createStr UTF8String], NULL, NULL, NULL);
19     
20     if (result == SQLITE_OK) {
21         NSLog(@"建立表成功");
22     } else {
23         NSLog(@"建立表失敗");
24     }      

  插入資料

1     // 當values不确定的情況下使用問号(?)代替,之後會進行值綁定的過程
 2     NSString *insertStr = @"insert into person(name, gender, age) values(?, ?, ?)";
 3     
 4     // 伴随指針
 5     sqlite3_stmt *stmt = NULL;
 6     
 7     // 預執行語句
 8     
 9     /*
10      int SQLITE_STDCALL sqlite3_prepare(
11         sqlite3 *db,
12         const char *zSql,
13         int nByte,
14         sqlite3_stmt **ppStmt,
15         const char **pzTail
16         );
17      */
18     // 第一個參數db:資料庫
19     // 第二個參數zSql:sql語句
20     // 第三個參數nByte:有正、負之分,例如:1,表示隻往後一個位元組;如果為負數,遇到特殊符号(\000,u000)才會結束讀取
21     // 第四個參數pzTail:是伴随指針,需要自己進行建立,會随着資料庫的相關操作确定其中問号(?)的值
22     // 第五個參數ppStmt:取值的時候取不全,剩下的值就都存在這裡
23     int result = sqlite3_prepare(db, [insertStr UTF8String], -1, &stmt, NULL);
24     
25     if (result == SQLITE_OK) {
26         
27         // 操作成功的方法裡進行問号(?)值的一些綁定設定
28         
29         // 第一個參數:伴随指針
30         // 第二個參數:? 的位置,從1開始
31         // 第三個參數:表示要插入的值
32         // 第四個參數:有正、負之分,例如:1,表示隻往後一個位元組;如果為負數,遇到特殊符号(\000,u000)才會結束讀取
33         // 第五個參數:回調函數
34         sqlite3_bind_text(stmt, 1, [name UTF8String], -1, NULL);
35         sqlite3_bind_text(stmt, 2, [gender UTF8String], -1, NULL);
36         sqlite3_bind_int64(stmt, 3, age);
37         
38         // sql語句執行完畢
39         // 執行伴随指針,根據伴随指針的執行情況來判斷是否插入成功[SQLITE_DONE代表伴随指針執行成功]
40         if (sqlite3_step(stmt) == SQLITE_DONE) {
41             NSLog(@"插入成功");
42         } else {
43             NSLog(@"插入失敗");
44         }
45         
46     } else {
47         NSLog(@"result = %d", result);
48     }
49     // 一定要釋放伴随指針
50     sqlite3_finalize(stmt);      

  更新資料

1     NSString *updateStr = @"update person set name = '悟空' where uid = ?";
 2     
 3     sqlite3_stmt *stmt = NULL;
 4     
 5     int result = sqlite3_prepare(db, updateStr.UTF8String, -1, &stmt, NULL);
 6     
 7     if (result == SQLITE_OK) {
 8         sqlite3_bind_int64(stmt, 1, uid);
 9         
10         if (sqlite3_step(stmt) == SQLITE_DONE) {
11             NSLog(@"更新資料成功");
12         } else {
13             NSLog(@"更新資料失敗");
14         }
15         
16     } else {
17         NSLog(@"result = %d", result);
18     }
19     sqlite3_finalize(stmt);      

  删除資料

1     NSString *deleteStr = @"delete from person where uid = ?";
 2     
 3     sqlite3_stmt *stmt = NULL;
 4     
 5     int result = sqlite3_prepare(db, deleteStr.UTF8String, -1, &stmt, NULL);
 6     
 7     if (result == SQLITE_OK) {
 8         sqlite3_bind_int64(stmt, 1, uid);
 9         
10         if (sqlite3_step(stmt) == SQLITE_DONE) {
11             NSLog(@"删除成功");
12         } else {
13             NSLog(@"删除失敗");
14         }
15         
16     } else {
17         NSLog(@"result = %d", result);
18     }
19     sqlite3_finalize(stmt);      

  查找所有資料

1     NSString *selectStr = @"select * from person";
 2     
 3     sqlite3_stmt *stmt = NULL;
 4     
 5     int result = sqlite3_prepare(db, selectStr.UTF8String, -1, &stmt, NULL);
 6     
 7     if (result == SQLITE_OK) {
 8         // 查找資料的時候當不知道有多少次的時候使用while循環
 9         // sqlite3_step(stmt) == SQLITE_ROW 代表逐行執行資料
10         while (sqlite3_step(stmt) == SQLITE_ROW) {
11             // 第一個參數:伴随指針
12             // 第二個參數:代表這個字段的位置【隻有帶問号的是從1開始,其餘所有都是從0開始】
13             int uid = sqlite3_column_int(stmt, 0);
14             NSLog(@"uid = %d", uid);
15             
16             // 在OC代碼中,要使用C語言的相關内容,應該使用utf-8
17             NSString *name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 1)];
18             NSLog(@"name = %@", name);
19             
20             NSString *gender = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 2)];
21             NSLog(@"gender = %@", gender);
22             
23             int age = sqlite3_column_int(stmt, 3);
24             NSLog(@"age = %d ***************", age);
25         }
26         
27     } else {
28         NSLog(@"result = %d", result);
29     }
30     sqlite3_finalize(stmt);