iOS開發 - SQLite資料庫(CRUD)
iOS中的資料存放區方式
Plist(NSArrayNSDictionary)
Preference(喜好設定NSUserDefaults)
NSCoding(NSKeyedArchiverNSkeyedUnarchiver)
SQLite3
Core Data
SQLite簡介
什麼是SQLite
SQLite是一款輕型的嵌入式資料庫
它佔用資源非常的低,在嵌入式裝置中,可能只需要幾百K的記憶體就夠了
它的處理速度比Mysql、PostgreSQL這兩款著名的資料庫都還快
什麼是資料庫
資料庫(Database)是按照資料結構來組織、儲存和管理資料的倉庫
資料庫可以分為2大種類
關係型資料庫(主流)
對象型資料庫
常用關係型資料庫
PC端:Oracle、MySQL、SQL Server、Access、DB2、Sybase
如何儲存資料
資料庫是如何儲存資料的
資料庫的儲存結構和excel很像,以表(table)為單位
資料庫儲存資料的步驟
建立一張表(table)
添加多個欄位(column,列,屬性)
添加多行記錄(row,每行存放多個欄位對應的值)
SQL語句
如何在程式運行過程中操作資料庫中的資料
那得先學會使用SQL語句
什麼是SQL
SQL(structured query language):結構化查詢語言 (SQL)
SQL是一種對關係型資料庫中的資料進行定義和操作的語言
SQL語言簡潔,文法簡單,好學好用
什麼是SQL語句
使用SQL語言編寫出來的句子代碼,就是SQL語句
在程式運行過程中,要想操作(增刪改查,CRUD)資料庫中的資料,必須使用SQL語句
SQL語句的特點
不區分大小寫(比如資料庫認為user和UsEr是一樣的)
每條語句都必須以分號 ; 結尾
SQL中的常用關鍵字有
select、insert、update、delete、from、create、where、desc、order、by、group、table、alter、view、index等等
資料庫中不可以使用關鍵字來命名表、欄位
SQL語句的種類
資料定義語句(DDL:Data Definition Language)
包括create和drop等操作
在資料庫中建立新表或刪除表(create table或 drop table)
資料動作陳述式(DML:Data Manipulation Language)
包括insert、update、delete等操作
上面的3種操作分別用於添加、修改、刪除表中的資料
資料查詢語句(DQL:Data Query Language)
可以用於查詢獲得表中的資料
關鍵字select是DQL(也是所有SQL)用得最多的操作
其他DQL常用的關鍵字有where,order by,group by和having
創表
格式create table 表名 (欄位名1 欄位類型1, 欄位名2 欄位類型2, …) ;create table if not exists 表名 (欄位名1 欄位類型1, 欄位名2 欄位類型2, …) ;樣本create table t_student (id integer, name text, age inetger, score real)
欄位類型
SQLite將資料劃分為以下幾種儲存類型:
integer : 整型值
real : 浮點值
text : 文本字串
blob : 位元據(比如檔案)
實際上SQLite是無類型的
就算聲明為integer類型,還是能儲存字串文本(主鍵除外)
建表時聲明啥類型或者不宣告類型都可以,也就意味著創表語句可以這麼寫:
create table t_student(name, age);
為了保持良好的編程規範、方便程式員之間的交流,編寫建表語句的時候最好加上每個欄位的具體類型
刪表
格式drop table 表名 ;drop table if exists 表名 ;樣本drop table t_student ;
插入資料(insert)
格式insert into 表名 (欄位1, 欄位2, …) values (欄位1的值, 欄位2的值, …) ;樣本insert into t_student (name, age) values (‘mj’, 10) ;注意資料庫中的字串內容應該用單引號 ’ 括住
更新資料(update)
格式update 表名 set 欄位1 = 欄位1的值, 欄位2 = 欄位2的值, … ; 樣本update t_student set name = ‘jack’, age = 20 ; 注意上面的樣本會將t_student表中所有記錄的name都改為jack,age都改為20
刪除資料(delete)
格式delete from 表名 ;樣本delete from t_student ;注意上面的樣本會將t_student表中所有記錄都刪掉
條件陳述式
如果只想更新或者刪除某些固定的記錄,那就必須在DML語句後加上一些條件條件陳述式的常見格式where 欄位 = 某個值 ; // 不能用兩個 =where 欄位 is 某個值 ; // is 相當於 = where 欄位 != 某個值 ; where 欄位 is not 某個值 ; // is not 相當於 != where 欄位 > 某個值 ; where 欄位1 = 某個值 and 欄位2 > 某個值 ; // and相當於C語言中的 &&where 欄位1 = 某個值 or 欄位2 = 某個值 ; // or 相當於C語言中的 ||
樣本將t_student表中年齡大於10 並且 姓名不等於jack的記錄,年齡都改為 5update t_student set age = 5 where age > 10 and name != ‘jack’ ;刪除t_student表中年齡小於等於10 或者 年齡大於30的記錄delete from t_student where age <= 10 or age > 30 ;猜猜下面語句的作用update t_student set score = age where name = ‘jack’ ;將t_student表中名字等於haha的記錄,height欄位的值 都改為 age欄位的值
DQL語句
格式select 欄位1, 欄位2, … from 表名 ;select * from 表名; // 查詢所有的欄位樣本select name, age from t_student ;select * from t_student ;select * from t_student where age > 10 ; // 條件查詢
起別名
格式(欄位和表都可以起別名)select 欄位1 別名 , 欄位2 別名 , … from 表名 別名 ; select 欄位1 別名, 欄位2 as 別名, … from 表名 as 別名 ;select 別名.欄位1, 別名.欄位2, … from 表名 別名 ;樣本select name myname, age myage from t_student ;給name起個叫做myname的別名,給age起個叫做myage的別名select s.name, s.age from t_student s ;給t_student表起個別名叫做s,利用s來參考資料表中的欄位
計算記錄的數量
格式select count (欄位) from 表名 ;select count ( * ) from 表名 ;樣本select count (age) from t_student ;select count ( * ) from t_student where score >= 60;
排序
查詢出來的結果可以用order by進行排序select * from t_student order by 欄位 ;select * from t_student order by age ;預設是按照升序排序(由小到大),也可以變為降序(由大到小)select * from t_student order by age desc ; //降序select * from t_student order by age asc ; // 升序(預設)也可以用多個欄位進行排序select * from t_student order by age asc, height desc ;先按照年齡排序(升序),年齡相等就按照身高排序(降序)
使用limit可以精確地控制查詢結果的數量,比如每次只查詢10條資料格式select * from 表名 limit 數值1, 數值2 ;樣本select * from t_student limit 4, 8 ;可以理解為:跳過最前面4條語句,然後取8條記錄
limit常用來做分頁查詢,比如每頁固定顯示5條資料,那麼應該這樣取資料第1頁:limit 0, 5第2頁:limit 5, 5第3頁:limit 10, 5…第n頁:limit 5*(n-1), 5猜猜下面語句的作用select * from t_student limit 7 ;相當於select * from t_student limit 0, 7 ;表示取最前面的7條記錄
簡單約束
建表時可以給特定的欄位設定一些約束條件,常見的約束有not null :規定欄位的值不能為nullunique :規定欄位的值必須唯一default :指定欄位的預設值(建議:盡量給欄位設定嚴格的約束,以保證資料的規範性)樣本create table t_student (id integer, name text not null unique, age integer not null default 1) ;name欄位不能為null,並且唯一age欄位不能為null,並且預設為1
主鍵約束
如果t_student表中就name和age兩個欄位,而且有些記錄的name和age欄位的值都一樣時,那麼就沒法區分這些資料,造成資料庫的記錄不唯一,這樣就不方便管理資料良好的資料庫編程規範應該要保證每條記錄的唯一性,為此,增加了主鍵約束也就是說,每張表都必須有一個主鍵,用來標識記錄的唯一性什麼是主鍵主鍵(Primary Key,簡稱PK)用來唯一地標識某一條記錄例如t_student可以增加一個id欄位作為主鍵,相當於人的身份證主鍵可以是一個欄位或多個欄位
在創表的時候用primary key聲明一個主鍵create table t_student (id integer primary key, name text, age integer) ;integer類型的id作為t_student表的主鍵主鍵欄位只要聲明為primary key,就說明是一個主鍵欄位主鍵欄位預設就包含了not null 和 unique 兩個約束如果想要讓主鍵自動成長(必須是integer類型),應該增加autoincrementcreate table t_student (id integer primary key autoincrement, name text, age integer) ;
利用外鍵約束可以用來建立表與表之間的聯絡外鍵的一般情況是:一張表的某個欄位,引用著另一張表的主鍵欄位建立一個外鍵create table t_student (id integer primary key autoincrement, name text, age integer, class_id integer, constraint fk_t_student_class_id_t_class_id foreign key (class_id) (id)) ; references t_class t_student表中有一個叫做fk_t_student_class_id_t_class_id的外鍵這個外鍵的作用是用t_student表中的class_id欄位引用t_class表的id欄位
表串連查詢
什麼是表串連查詢需要聯合多張表才能查到想要的資料表串連的類型內串連:inner join 或者 join (顯示的是左右表都有完整欄位值的記錄)左外串連:left outer join (保證左表資料的完整性)樣本查詢0316iOS班的所有學生select s.name,s.age from t_student s, t_class c where s.class_id = c.id and c.name = ‘0316iOS’;
SQLite資料庫(CRUD)執行個體
#import ViewController.h#import @interface ViewController (){ sqlite3 *_db; //建立資料庫的執行個體}- (IBAction)insertData;- (IBAction)deleteData;- (IBAction)updateData;- (IBAction)selectData;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; //0.獲得沙箱中的資料庫檔案名 NSString * fileName=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@student.sqlite]; NSLog(@fileName = %@,fileName); //1.建立(開啟資料庫,如果資料庫檔案不存在會自動建立) int result=sqlite3_open(fileName.UTF8String, &_db); if (result==SQLITE_OK) { NSLog(@成功開啟資料庫); //2.創表 const char *sql = create table if not exists t_student (id integer primary key autoincrement, name text, age integer);; char *errorMessage=NULL; int result=sqlite3_exec(_db, sql, NULL, NULL, &errorMessage); if (result==SQLITE_OK) { NSLog(@成功建立表); }else{ NSLog(@建立表失敗: %s,errorMessage); } }else{ NSLog(@開啟資料庫失敗); }}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}/** * 插入資料 */- (IBAction)insertData { for (int i=0; i<20; i++) { NSString *name =[NSString stringWithFormat:@學生-%d,arc4random()%100]; int age=arc4random()%100; NSString *sql = [NSString stringWithFormat:@insert into t_student (name, age) values('%@', %d);, name, age]; char *errorMessage=NULL; int result=sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errorMessage); if (result==SQLITE_OK) { NSLog(@成功添加資料); }else{ NSLog(@添加資料失敗:%s,errorMessage); } }}/** * 刪除資料 */- (IBAction)deleteData { //1.定義sql語句 const char *sql = delete from t_student where age=9;; //2.定義一個stmt存放結果集 sqlite3_stmt *stmt=NULL; //3. 檢測SQL語句的合法性 int result =sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result ==SQLITE_OK) { //4.執行SQL語句,從結果集中取出資料 while (sqlite3_step(stmt)==SQLITE_ROW) { //獲得這行對應的資料 //獲得第0列的id int sid=sqlite3_column_int(stmt, 0); //獲得第一列的name const unsigned char * sname=sqlite3_column_text(stmt, 1); //獲得第2列的age int sage=sqlite3_column_int(stmt, 1); NSLog(@%d %s %d,sid,sname,sage); } NSLog(@刪除成功!); }else{ NSLog(@刪除失敗!); }}/** * 更新資料 */- (IBAction)updateData { //1.定義sql語句 const char *sql = update t_student set name = ‘jack’, age = 20 ;; //2.定義一個stmt存放結果集 sqlite3_stmt *stmt=NULL; //3. 檢測SQL語句的合法性 int result =sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result ==SQLITE_OK) { //4.執行SQL語句,從結果集中取出資料 while (sqlite3_step(stmt)==SQLITE_ROW) { //獲得這行對應的資料 //獲得第0列的id int sid=sqlite3_column_int(stmt, 0); //獲得第一列的name const unsigned char * sname=sqlite3_column_text(stmt, 1); //獲得第2列的age int sage=sqlite3_column_int(stmt, 1); NSLog(@%d %s %d,sid,sname,sage); } NSLog(@更新成功!); }else{ NSLog(@更新失敗!); }}/** * 查詢資料 */- (IBAction)selectData { //1.定義sql語句 const char *sql = select id, name, age from t_student where name = ?;; //2.定義一個stmt存放結果集 sqlite3_stmt *stmt=NULL; //3. 檢測SQL語句的合法性 int result =sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL); if (result ==SQLITE_OK) { NSLog(@查詢語句合法); //4.執行SQL語句,從結果集中取出資料 while (sqlite3_step(stmt)==SQLITE_ROW) { //獲得這行對應的資料 //獲得第0列的id int sid=sqlite3_column_int(stmt, 0); //獲得第一列的name const unsigned char * sname=sqlite3_column_text(stmt, 1); //獲得第2列的age int sage=sqlite3_column_int(stmt, 1); NSLog(@%d %s %d,sid,sname,sage); } }else{ NSLog(@查詢語句非法); }}