一.SQLite的介紹
1.為什么要存儲數據?
1.1 手機數據大多都是從網絡加載的,不存儲,每次滾動界面都要從新發送網絡請求加載數據,浪費流量
1.2 當用戶沒網的時候,就不能正常顯示界面了
1.3 將數據存儲到本地,不用每次加載,沒網的時候也可從本地存儲的數據拿來顯示
2.存儲數據的方式
Plist(NSArray\NSDictionary)
特點: 只能存儲系統自帶的數據類型, 比如NSDictory, NSArray等等. 自定義的對象無法存儲
Preference(偏好設置\NSUserDefaults)
特點: 本質就是一個plist文件; 也是只能存儲系統自帶的數據類型, 自定義的對象無法存儲
NSCoding(NSKeyedArchiver\NSkeyedUnarchiver)
特點: 可以存儲自己定義的數據類型, 但是都是一次性的全數據操作
SQLite3
特點: 存儲一些大批量的數據, 排序, 統計等操作
Core Data
特點: 對SQLite3的一層面向對象的包裝, 本質還是要轉換成為對應的SQL語句去執行
在所有的存儲方式中,SQLite速度最快,效率最高.
3.什么是SQLite?
- SQLite是一款輕型的嵌入式關系數據庫
- 它占用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了
- 目前廣泛應用於移動設備中存儲數據(Android/iOS)
- 處理數據的速度非常快,效率非常高
4.什么是數據庫?
- 數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫(類似於excel表格)
- 數據庫可以分為2大種類(了解)
- 關系型數據庫(主流)
- 對象型數據庫
5.關系型數據庫介紹
二.Navicat軟件的破解
1.什么是Navicat?
Navicat是數據庫管理軟件,支持大部分主流數據庫(包括SQLite)(收費,要破解)
可以通過圖形化界面的方式來管理數據庫
2.有破解版,可以去網上搜索下載,自己安裝,這里不做介紹
三.Navicat軟件的使用
1.創建SQLite數據庫
2.創建表
2.1 雙擊打開數據庫,在tables中點擊右鍵,選中NewTable
2.2 創建表中對應的字段,點擊”+”添加字段
2.3 保存,要設置表格名稱. 名稱規范: t_名稱 如: t_student
3.設置主鍵,添加數據
3.1 什么是主鍵
主鍵就相當於身份證一樣,用來區分每一條數據
3.2 設置主鍵注意點
3.3 添加,刪除,修改數據
3.31 直接點擊”+” 添加數據
注意:主鍵的值不要修改
3.32 刪除,選中一行,點擊”-“ 直接刪除
注意:刪除一組數據后,主鍵值就不會再被回收使用. 一個主鍵值只對應一條數據,無論數據是否存在
3.33 修改數據
雙擊想要修改的數據,直接修改
四.SQLite的使用步驟
1.創建數據庫(一個用於存儲數據的文件)
通常后綴名為: .db 或 .sqlite
2.創建表用於存儲數據
- 創建表時需要指定該表有哪些字段
- 比如學生表有:學號/姓名/年齡/身高等
3.對表進行增刪改查操作
- 比如添加一條學生數據:型號:1/姓名:why/年齡:18/身高:1.88
五.SQL簡介
1.怎么在程序中使用SQLite?
真實使用SQLite時用代碼來操作的
2.怎么用代碼操作SQLite?
使用SQL語句來操作
3.SQL介紹 不做過多介紹,直接看下定義就行了
六.在代碼中使用DDL(數據定義語句)
1.先導入libsqlite3.tba框架(c語言)
2.創建橋接文件,配置橋接文件(不會的話,看之前筆記)
3.創建數據庫
// 創建數據庫 // 文件路徑 : // 1.獲取數據庫的存放路徑(沙盒中) let filePath = "/Users/xiaomage/Desktop/123.sqlite" let cString = filePath.cStringUsingEncoding(NSUTF8StringEncoding)! // 2.定義數據庫對象(后面還要用,定義一個屬性替代) // var db : COpaquePointer = nil // 3.打開/創建 數據庫對象 if sqlite3_open(cString, &db) == SQLITE_OK { print("創建/打開數據庫成功") } else { print("失敗") } }
4.創建表
4.1 創建SQL語句
4.2 執行語句(要對語句進行判斷) if 語句 == SQLITE_OK
4.3 創建表格式
CREATE TABLE IF NOT EXISTS '表名' (
'字段名' 類型(INTEGER, REAL, TEXT, BLOB)
NOT NULL 不允許為空
PRIMARY KEY 主鍵
AUTOINCREMENT 自增長,
'字段名2' 類型,
...
)
4.4 語句說明
- CREATE TABLE:創建一張表
- IF NOT EXISTS:不存在則創建
- 't_student':表的名稱
- NOT NULL:不允許為空
- PRIMARY KEY:主鍵
- AUTOINCREMENT:自動增加
- 'id' INTEGER:有一個ID字段,類型是INTEGER
5.刪除表
5.1刪除表的格式
DROP TABLE IF EXISTS '表名';
5.2 語句說明
DROP TABLE:刪除表
IF EXISTS:存在則刪除
'表名':要刪除的表的名稱
1 // 1.獲取要執行的SQL語句 2 let createTableSQL = "DROP TABLE IF EXISTS t_student;" 3 4 // 2.執行語句 5 if sqlite3_exec(db, createTableSQL.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil) == SQLITE_OK { 6 print("刪除表成功") 7 } else { 8 print("刪除表失敗") 9 } 10 }
6.封裝SQL語句
6.1 創建/打開數據庫的代碼全部一樣,可以封裝起來
6.2 創建語句,執行語句步驟都一樣,只有 語句的內容不一樣,可以把語句當做參數,封裝起來
6.3 封裝工具類,最好把實例對象設計為單例
class SQLiteManager { // 設計單例對象 static let shareInstance : SQLiteManager = SQLiteManager() // 數據庫對象 var db : COpaquePointer = nil } // MARK:- 打開數據庫的操作 extension SQLiteManager { func openDB(filePath : String) -> Bool { // 1.將Swift字符串轉成C語言的字符串 let cString = filePath.cStringUsingEncoding(NSUTF8StringEncoding)! // 3.打開/創建數據庫對象 return sqlite3_open(cString, &db) == SQLITE_OK } } // MARK:- 執行SQL語句 extension SQLiteManager { func execSQL(sqlString : String) -> Bool { // 1.將Swift字符串轉成C語言的字符串 let cSQLString = sqlString.cStringUsingEncoding(NSUTF8StringEncoding)! // 2.執行語句 return sqlite3_exec(db, cSQLString, nil, nil, nil) == SQLITE_OK } }
七.在代碼中使用DML(數據操作語句)
1.插入數據
1.1 插入數據格式
INSERT INTO 't_student' (name, age, height) VALUES ('why', 18, 1.88);
1.2 語句說明
- INSERT INTO: 插入數據
- 't_student': 在哪一個表中插入數據
- (數據的字段): 給哪些字段插入數據
- VALUES ('why', 18, 1.88): 插入的具體值
// 1.插入數據(獲取插入語句) let insertSQL = "INSERT INTO t_student (name, age, height) VALUES ('why', 18, 1.88);" // 2.執行語句 SQLiteManager.shareInstance.execSQL(insertSQL)
2.更新數據
1.1 更新數據格式
UPDATE 't_student' SET 字段 = '值' WHERE 條件判斷;
1.2 語句說明
- UPDATE: 跟新數據
- 't_student': 在哪一個表中更新數據
- SET 字段 = '值': 更新怎樣的數據
- WHERE 條件判斷: 更新哪些數據
// 1.獲取更新語句 let updateSQL = "UPDATE t_student SET name = 'yz';" // 2.執行語句 SQLiteManager.shareInstance.execSQL(updateSQL)
3.刪除數據
3.1 刪除數據格式
DELETE FROM t_student;
DELETE FROM t_student WHERE age < 50;
3.2 語句說明
- DELETE FROM: 從表中刪除數據
- t_student : 表名
- 可以跟條件也可以不跟:不跟表示刪除所有的數據
// 1.獲取刪除語句 let deleteSQL = "DELETE FROM t_student;" // 2.執行語句 SQLiteManager.shareInstance.execSQL(deleteSQL)
4.真實開發如何插入數據
4.1 真實開發插入數據,不可能一條一條去寫
4.2 一般來說,我們開發都是面向模型的
4.3 可以把要插入的數據包裝成模型
4.4 在模型中提供方法,快速插入數據
4.5 遍歷模型數組,利用模型中快速插入數據的方法插入數據
5.怎么把數據包裝成模型?
遍歷數據,把數據的每一個字段作為模型的屬性保存起來
// 模擬從網絡服務器中請求到很多數據(實際中數據是網絡來的,這里自己寫模擬) for _ in 0..<100 { let name = "zs\(arc4random_uniform(100))" let age = Int(10 + arc4random_uniform(10)) let height = 1 + Double(arc4random_uniform(10)) / 10.0 let stu = Student(name: name, age: age, height: height) stus.append(stu) }
模型中代碼:
1 class Student: NSObject { 2 var name : String = "" 3 var age : Int = 0 4 var height : Double = 0.0 5 6 init(name : String, age : Int, height : Double) { 7 self.name = name 8 self.age = age 9 self.height = height 10 } 11 } 12 13 extension Student { 14 func insertDB() { 15 // 1.插入數據(獲取插入語句) 16 let insertSQL = "INSERT INTO t_student (name, age, height) VALUES ('\(name)', \(age), \(height));" 17 // 2.執行語句 18 SQLiteManager.shareInstance.execSQL(insertSQL) 19 } 20 }
控制器中快速插入
for stu in stus { stu.insertDB() }
6.插入數據的優化
6.1 如果有大量數據插入,在主線程執行,會阻塞ui
6.2 插入大量數據怎么優化?
6.21 在子線程進行數據插入
6.22 手動開啟事務
如果一條條數據進行插入時,那么每插入一條數據就會開啟一次事務.(開啟事務耗時)
但是如果有明確的開啟事務,那么系統就不會在插入每條數據時,再開啟事務
1 dispatch_async(dispatch_get_global_queue(0, 0)) { 2 //獲取插入數據開始時間 3 let startTime = CACurrentMediaTime() 4 // 開啟事務 5 let startSQL = "BEGIN TRANSACTION;" 6 SQLiteManager.shareInstance.execSQL(startSQL) 7 8 for stu in self.stus { 9 stu.insertDB() 10 } 11 //關閉事務 12 let commitSQL = "COMMIT TRANSACTION;" 13 SQLiteManager.shareInstance.execSQL(commitSQL) 14 //獲取插入數據結束時間 15 let endTime = CACurrentMediaTime() 16 //獲取插入數據耗時 17 print(endTime - startTime) 18 } 19 }
八.在代碼中使用DQL(數據查詢語句)
1.查詢語句
2.查詢數據代碼實現步驟
2.1 獲取查詢語句
2.2 執行查詢語句(得到的結果保存到數組中,最好是字典數組)
2.3 遍歷數組,字典轉模型
2.4 從模型中讀取數據
代碼實現:
1 // 1.獲取查詢語句 2 let querySQL = "SELECT * FROM t_student LIMIT 30, 30;"; 3 4 // 2.執行語句 (執行語句封裝到了一個方法里面) 5 guard let dictArray = SQLiteManager.shareInstance.querySQL(querySQL) else { 6 return 7 } 8 9 // 3.遍歷數組 10 var tempArray = [Student]() 11 for dict in dictArray { 12 // 字典轉模型 13 tempArray.append(Student(dict: dict)) 14 } 15 16 for stu in tempArray { 17 print(stu.name, stu.age) 18 } 19 20 //執行語句代碼實現 21 func querySQL(querySQL : String) -> [[String : NSObject]]? { 22 // 0.將Swift字符串轉成C語言字符串 23 let cString = querySQL.cStringUsingEncoding(NSUTF8StringEncoding)! 24 25 // 1.定義游標(指針) 26 var stmt : COpaquePointer = nil 27 28 // 2.給游標賦值 29 // 1> 參數一: 數據庫對象 30 // 2> 參數二: SQL語句 31 // 3> 參數三: 該SQL語句的長度 -1 --> 系統自動計算 32 // 4> 參數四: 游標的地址 33 guard sqlite3_prepare_v2(db, cString, -1, &stmt, nil) == SQLITE_OK else { 34 return nil 35 } 36 37 // 3.取出所有的數據 38 // 3.1.定義字典數組 39 var dictArray = [[String : NSObject]]() 40 41 // 3.2.判斷是否有該條數據 42 while sqlite3_step(stmt) == SQLITE_ROW { 43 // 3.3.獲取字段的個數 44 let count = sqlite3_column_count(stmt) 45 // 3.4.定義字典 46 var dict = [String : NSObject]() 47 // 3.5.遍歷每一個字典 48 for i in 0..<count { 49 // 3.6.取出該列的鍵 50 let ckey = sqlite3_column_name(stmt, i) 51 guard let key = String(UTF8String : ckey) else { 52 continue 53 } 54 // 3.7.取出該列的值 55 let cvalue = UnsafePointer<Int8>(sqlite3_column_text(stmt, i)) 56 //將c語言字符串轉成swift字符串 57 let value = String(UTF8String : cvalue) 58 59 // 3.8.將鍵值對放入到字典中 60 dict[key] = value 61 } 62 // 3.9.將字典放入到數組中 63 dictArray.append(dict) 64 } 65 return dictArray 66 } 67 }
九.FMDB框架的使用
1.FMDB框架的作用?
FMDB是用來簡化操作數據庫的框架
2.FDMB的基本使用
2.1 創建數據庫
private lazy var db : FMDatabase = FMDatabase(path: "/Users/lgp/Desktop/321.sqlite") // 創建FMDatabase對象 // 打開/創建數據 if db.open() { print("打開成功") } else { print("失敗") }
2.2 創建/刪除 表 插入/更新/刪除 數據
本質都是一樣的只有語句的內容不一樣
將語句內容換成對應的操作,就能執行該項操作(和SQLite語句一樣)
// 1.獲取創建表的語句 let createSQL = "INSERT INTO t_person (name, age, height) VALUES ('why', 18, 1.88);" // 2.執行語句 db.executeUpdate(createSQL, withArgumentsInArray: nil)
2.3 查詢數據
var db : FMDatabase?
1 func querySQL(querySQL : String) -> [[String : NSObject]]? { 2 // 0.判斷db是否有值 db定義為屬性 3 guard let db = db else { 4 return nil 5 } 6 // 1.執行查詢語句 結果為集合 7 let results = db.executeQuery(querySQL, withArgumentsInArray: nil) 8 9 // 2.獲取數據 10 // 2.0.定義數據 11 var dictArray = [[String : NSObject]]() 12 13 // 2.1.判斷結果集中是否有內容 14 while results.next() { 15 16 let count = results.columnCount() 17 18 var dict = [String : NSObject]() 19 20 for i in 0..<count { 21 let key = results.columnNameForIndex(i) 22 let value = results.stringForColumnIndex(i) 23 24 dict[key] = value 25 } 26 dictArray.append(dict) 27 } 28 return dictArray 29 }
