第二章 Senior進(jìn)階 數(shù)據(jù)庫
一、數(shù)據(jù)庫管理系統(tǒng)
1.SQL:SQL是Structured Query Language(結(jié)構(gòu)化查詢語言)的縮寫。SQL是專為數(shù)據(jù)庫而建立的操作命令集,是一種功能齊全的數(shù)據(jù)庫語言。
2.常見的數(shù)據(jù)庫“
1.My SQL:MySQL是一個(gè)精巧的SQL數(shù)據(jù)庫管理系統(tǒng),而且是開源的數(shù)據(jù)管理系統(tǒng)。MySQL主要目標(biāo)是快速、健壯和易用。由于它的強(qiáng)大功能、靈活性、豐富的應(yīng)用編程接口(API)以及精巧的系統(tǒng)結(jié)構(gòu),受到了廣大自由軟件愛好者甚至是商業(yè)軟件用戶的青睞
2.Oracle:Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關(guān)系數(shù)據(jù)庫管理系統(tǒng)。系統(tǒng)可移植性好、使用方便、功能強(qiáng)。
3.數(shù)據(jù)庫的好處(特征):
1.以一定方式存儲在一起
2.能為多個(gè)用戶共享
3.具有盡可能少的冗余代碼
4.與程序彼此獨(dú)立的數(shù)據(jù)集合
4.數(shù)據(jù)庫
1.定義:數(shù)據(jù)庫(Database)是按照數(shù)據(jù)結(jié)構(gòu)來組織、存儲和管理數(shù)據(jù)的倉庫
2.分類:關(guān)系型數(shù)據(jù)庫(主流)、對象型數(shù)據(jù)庫、層次式數(shù)據(jù)庫、網(wǎng)格式數(shù)據(jù)庫
3.常用的關(guān)系型數(shù)據(jù)庫
PC端:Oracle、MySQL、SQL Server、Access、DB2、Sybase
嵌入式\移動客戶端:SQLite
5.SQLite(http://www.sqlite.org/doc.html)是一個(gè)輕量級的關(guān)系數(shù)據(jù)庫。SQLite最初的設(shè)計(jì)目標(biāo)是用于嵌入式系統(tǒng),它占用資源非常少,在嵌入式設(shè)備中,只需要幾百k的內(nèi)容就夠了,目前應(yīng)用于Android、iOS等智能手機(jī)。iOS使用SQLite時(shí),只需加入libsqlite3.0.tbd以及引入sqlite3.h頭文件即可。
6.表:是數(shù)據(jù)庫中一個(gè)非常重要的對象,是其他對象的基礎(chǔ)。根據(jù)信息的分類情況,一個(gè)數(shù)據(jù)庫中可能包含若干個(gè)數(shù)據(jù)表
7.字段:標(biāo)的“列”稱為“字段”,每一個(gè)字段包含某一個(gè)專題的信息。用來標(biāo)識本列數(shù)據(jù)類型
8.記錄:是指對應(yīng)于數(shù)據(jù)表中一行信息的一組完整的相關(guān)信息。用來表示表中一行的信息
二、SQL語句
1.SQLite是無類型的數(shù)據(jù)庫,可以保存任何類型的數(shù)據(jù),對于SQLite來說對字段不指定類型是完全有效的(==注:良好的編程習(xí)慣應(yīng)該要為字段標(biāo)注類型==)
2.SQLite近似類型規(guī)則
為了使SQLite和其他數(shù)據(jù)庫間的兼容性最大化,sqlite支持“類型近似”的觀點(diǎn),列的類型近似指的是存儲在列上的數(shù)據(jù)的推薦類型
1.如果類型字符串中包含“INT”,那么該字段的親緣類型是INTEGER。
2.如果類型字符串中包含“CHAR”、“CLOB”或者“TEXT”,那么該字段的親緣類型是TEXT,如VARCHAR。
3.如果類型字符串中包含“BLOB”。那么該字段的親緣類型是NONE。
4.如果類型字符串中包含“REAL”、“FLOA”或“DOUB”,那么該字段的親緣類型是REAL
5.其余情況下、字段的親緣類型為NUMERIC。
3.SQLite的字段約束條件
NOT NULL -- 非空 該字段數(shù)據(jù)不能為空
UNIQUE ----唯一 該字段數(shù)據(jù)不能重復(fù)
PRIMARY KEY ---主鍵 用于唯一標(biāo)識一條數(shù)據(jù)
FOREIGN KEY ---外鍵 該字段作為另一個(gè)表的主鍵,聯(lián)表查詢
CHECK --- 條件檢查,確保一列中的所有值滿足一定條件 該字段數(shù)據(jù)必須滿足一定條件
DWDAULT ---- 默認(rèn) 該字段數(shù)據(jù)可以給定默認(rèn)值
AUTOINCREATEMENT --- 自增型變量 該字段數(shù)據(jù)如果為整型可以自動加1
4.SQLite字段約束條件:PRIMARY KEY -- 主鍵
首先,數(shù)據(jù)表中每一條記錄都有一個(gè)主鍵,這就像我們每個(gè)人的身份證號碼、員工號、銀行賬號;反過來說,每一個(gè)主鍵對應(yīng)著一條數(shù)據(jù)記錄,所以,主鍵必須是唯一的
其次,一般情況下注鍵同時(shí)也是也是一個(gè)索引,所以通過逐漸查找記錄速度比較快
第三,在關(guān)系型數(shù)據(jù)庫中,一個(gè)表的主鍵可以作為另一個(gè)標(biāo)的外鍵,這樣,這兩個(gè)表之間就通過這個(gè)鍵建立了關(guān)系
最后,逐漸一般是整數(shù)或者字符串,只要保證唯一就行。在SQLite中,主鍵如果是整數(shù)類型,該列的值可以自動增長
5.SQL語句:
1.建表命令(Create table)
create table if not exists 表名 (字段1 約束1 約束2····,字段2 約束1 約束2,····);
2.數(shù)據(jù)插入命令(Insert)
insert into 表名 (字段1,字段2,···) values (字段1值,字段2值,···);
注意:要插入的數(shù)據(jù)要和字段順序相同
3.數(shù)據(jù)庫更新命令(Update)
update 表名 set 字段名1 = 修改值1,字段名2 = 修改值2,···· where 條件;
注意:關(guān)鍵字 update set
條件可以有一個(gè)或多個(gè)。多個(gè)條件使用and(與),or(或)連接
4.數(shù)據(jù)庫刪除命令(Delete
delete from 表名 where 條件;
5.數(shù)據(jù)庫檢索命令(Select)
select 要查找的字段 form 表名 where 條件
注意:要查找的字段,如果查找所有字段可以使用通配符 *
三、iOS的數(shù)據(jù)庫技術(shù)實(shí)現(xiàn)
1.Linux系統(tǒng)級的SQLite技術(shù)實(shí)現(xiàn)框架
Xcode 6 中l(wèi)ibsqlite3.0.dylib
Xcode 7 中l(wèi)ibsqlite3.0.tbd
2.使用SQLite數(shù)據(jù)庫的流程
1.引入<sqlite3.h>頭文件
//包含了sqlite數(shù)據(jù)庫操作所需要的所有函數(shù)
#import <sqlite3.h>
2.在.m文件中聲明一個(gè)sqlite3的屬性
//數(shù)據(jù)庫句柄 這個(gè)屬性相當(dāng)于數(shù)據(jù)庫的對象
sqlite3* sqliteHandle;
3.創(chuàng)建數(shù)據(jù)庫文件將要存儲的文件路徑
- (NSString*)dbPath{
NSString* documentsPathString = [[SandBoxPaths documentsPath] stringByAppendingPathComponent:@"textDB.sqlite"];
return documentsPathString;
}
4.打開數(shù)據(jù)庫
- (void)createDataBase{
//創(chuàng)建數(shù)據(jù)庫文件的函數(shù),如果數(shù)據(jù)庫文件存在,那么這個(gè)方法就是打開數(shù)據(jù)庫文件,如果數(shù)據(jù)庫不文件存在,這個(gè)方法就是創(chuàng)建數(shù)據(jù)庫文件,再打開
//第一個(gè)參數(shù):數(shù)據(jù)庫文件的路徑,并且需要將其轉(zhuǎn)換為char * 類型(是C語言的字符串類型)
//第二個(gè)參數(shù):數(shù)據(jù)庫文件的句柄,取地址 &(and) 符號就是取地址
//將數(shù)據(jù)庫句柄指向數(shù)據(jù)庫內(nèi)存,我們對數(shù)據(jù)庫的操作,都是通過句柄來完成的
int result = sqlite3_open([self dbPath].UTF8String, & sqliteHandle);
if(result == SQLITE_OK){
NSLog(@"數(shù)據(jù)庫打開成功");
}else{
NSLog(@"數(shù)據(jù)庫打開失敗 --- %d",result);
}
}
3.執(zhí)行SQL命令(建表,增刪改查)
1.非查詢操作(無返回結(jié)果集的操作) 插入 更新 刪除等
//參數(shù)為需要執(zhí)行的sql語句
- (void)noQueryOpertion:(NSString*)sql{
//用來執(zhí)行無返回結(jié)果的操作
//第一個(gè)參數(shù):數(shù)據(jù)庫的句柄,所有對數(shù)據(jù)庫的操作都是通過句柄來完成的,所以這里需要句柄
//第二個(gè)參數(shù):要執(zhí)行的sql語句
//第三個(gè)參數(shù):回調(diào)函數(shù),exec函數(shù)執(zhí)行完畢之后會執(zhí)行的函數(shù)。如果需要在該操作執(zhí)行完畢的時(shí)候做一些其他操作,就需要實(shí)現(xiàn)該回調(diào)函數(shù),一般我們直接NULl
//第四個(gè)參數(shù):回調(diào)方法的第一個(gè)參數(shù)
//第五個(gè)參數(shù):錯(cuò)誤日志
int result = sqlite3_exec(sqliteHandle, sql.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@"操作執(zhí)行成功");
}else{
NSLog(@"操作執(zhí)行失敗");
}
}
2.查詢操作
- (void)queryWithSql:(NSString*)sql{
//伴隨指針 當(dāng)我們進(jìn)行查詢操作的時(shí)候,該指針可以理解為存儲一條一條的記錄。我們獲取一條記錄的所有信息都是通過伴隨指針。
sqlite3_stmt * stmt = NULL;
//預(yù)執(zhí)行sql語句,如果預(yù)執(zhí)行成功說明,那么我們就可以獲取一條一條的記錄;如果預(yù)執(zhí)行失敗,說明我們的sql語句有問題 不能獲取表中的記錄信息
//第一個(gè)參數(shù):數(shù)據(jù)庫句柄
//第二個(gè)參數(shù):要執(zhí)行的SQ語句
//第三個(gè)參數(shù):要執(zhí)行的長度,如果全部執(zhí)行,這里就賦值為-1
//第四個(gè)參數(shù):伴隨指針
//第五個(gè)參數(shù):如果sql語句不全部執(zhí)行,該參數(shù)保存未執(zhí)行的sql語句
int result = sqlite3_prepare(sqliteHandle, sql.UTF8String, -1, &stmt, NULL);
//初始化一個(gè)可變數(shù)組,用來存放所有的記錄,每一條記錄就相當(dāng)于一個(gè)字典
NSMutableArray* allDataMArray = [[NSMutableArray alloc] init];
//判斷是否預(yù)執(zhí)行成功
if(result == SQLITE_OK){
//說明預(yù)執(zhí)行成功,可以取表中的數(shù)據(jù)了
//通過while循環(huán)將表中的每一條記錄取出
//step方法沒執(zhí)行一次,伴隨指針就會執(zhí)行下一條記錄;當(dāng)所有的記錄都取完之后,step函數(shù)的返回值就不等于SQLITE_ROW了,循環(huán)也就停止了
while (sqlite3_step(stmt) == SQLITE_ROW) {
//每次執(zhí)行while循環(huán),都是一條新的紀(jì)錄,一條新記錄要對應(yīng)一個(gè)新字典。
NSMutableDictionary* mDictionary = [[NSMutableDictionary alloc] init];
//進(jìn)入循環(huán)體內(nèi),伴隨指針就相當(dāng)于當(dāng)前取出的一條記錄
//從記錄中取值,是一個(gè)字段一個(gè)字段取出
//取出第0列的值
//
const unsigned char* name = sqlite3_column_text(stmt, 0);
//將char*類型轉(zhuǎn)換為我們OC中可用的字符串類型
NSString* nameString = [[NSString alloc] initWithCString:(const char *)name encoding:NSUTF8StringEncoding];
//將數(shù)據(jù)存入到字典中
[mDictionary setObject:nameString forKey:@"name"];
//取出第一列的值,存入字典中
int age = sqlite3_column_int(stmt,1);
//將int數(shù)據(jù)轉(zhuǎn)換為NSNumber放入字典
[mDictionary setObject:@(age) forKey:@"age"];
//取出第二列的值
const unsigned char* gender = sqlite3_column_text(stmt, 2);
//將char*類型轉(zhuǎn)換為我們OC中可用的字符串類型
NSString* genderString = [NSString stringWithCString:(const char*)gender encoding:NSUTF8StringEncoding];
[mDictionary setObject:genderString forKey:@"gender"];
//將該字典添加到可變數(shù)組中
[allDataMArray addObject:mDictionary];
}
}else{
NSLog(@"預(yù)執(zhí)行失敗 --- %d",result);
}
//將伴隨指針?biāo)谐钟械馁Y源釋放
sqlite3_finalize(stmt);
//打印結(jié)果
NSLog(@"查詢結(jié)果 ---- %@",allDataMArray);
}
3.SQL語句操作
1.建表操作
NSString* sql = @"create table if not exists stu (name text,age integer,gender text)";
[self noQueryOpertion:sql];
2.插入一條數(shù)據(jù)
NSString* insertSql = @"insert into stu values ('kk',16,'男')";
[self noQueryOpertion:insertSql];
3.更新操作
NSString* updateSql = @"update stu set age = 18 where age = 16";
[self noQueryOpertion:updateSql];
4.刪除一條數(shù)據(jù)
NSString* deleteSql = @"delete from stu where name = 'kk'";
[self noQueryOpertion:deleteSql];
5.查詢方法
[self queryWithSql:@"select * from stu"];
4.關(guān)閉數(shù)據(jù)庫
sqlite3_close(sqliteHandle);
3.SQLite常用系列函數(shù)
1.sqlite3_exec()可以執(zhí)行任何SQL語句,比如創(chuàng)表、更新、插入和刪除操作。但是一般不用它執(zhí)行查詢語句,因?yàn)樗粫祷夭樵兊降臄?shù)據(jù)
2.SQLite語法:預(yù)執(zhí)行
sqlite3_prepare()
這個(gè)函數(shù)將sql文本轉(zhuǎn)換為一個(gè)準(zhǔn)備語句(prepared statement)對象,同時(shí)返回這個(gè)對象的指針。它實(shí)際上并不執(zhí)行(evaluate)這個(gè)SQL語句,他僅僅為執(zhí)行準(zhǔn)備這個(gè)sql語句
sqlite3_bind_*()
給宿主參數(shù)(host parameters)綁定值(*代表不同類型)
sqlite3_step ()
一次或多次來執(zhí)行有前面sqlite3_prepare創(chuàng)建的準(zhǔn)備語句
sqlite3_column()
這個(gè)過程從執(zhí)行sqlite3_step()執(zhí)行一個(gè)準(zhǔn)備語句得到的結(jié)果集的當(dāng)前行中返回一個(gè)列。每次sqlite3_step得到一個(gè)結(jié)果集的列停下后,這個(gè)過程就可以被多次調(diào)用去查詢這個(gè)行的各列的值。對列操作是有多個(gè)函數(shù),均以sqlite3_column為前綴
sqlite3_finalize()
這個(gè)過程銷毀前面被sqlite3_prepare創(chuàng)建的準(zhǔn)備語句,每個(gè)準(zhǔn)備語句都必須使用這個(gè)函數(shù)去銷毀以防止內(nèi)存泄露
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。