封裝自定義數(shù)據(jù)庫的工具類
class SQLiteTool: NSObject {
// 懶加載數(shù)據(jù)庫工具類的單例對象
static let shareIstance = SQLiteTool()
// 指向數(shù)據(jù)庫的指針
var db: COpaquePointer = nil
// 重構(gòu)
override init() {
super.init()
let path = "/Users/yangxiaoming/Desktop/sql/Untitled.sqlite"
// 打開數(shù)據(jù)庫
if sqlite3_open(path, &db) != SQLITE_OK {
print("數(shù)據(jù)庫打開成功")
}else {
print("數(shù)據(jù)庫打開失敗")
// 創(chuàng)建表
createTtable()
}
}
}
然后可以在該工具類中定義一些需要實(shí)現(xiàn)的操作的方法:對表中數(shù)據(jù)的曾粱快、刪屹堰、改碟渺、查的方法(這里封裝了所有的操作的一個方法鲜锚,可以根據(jù)傳入進(jìn)來的sql語句,然后進(jìn)行執(zhí)行)
- exec表示執(zhí)行的意思
func excuteSql(sql: String) -> Bool {
// 2. 執(zhí)行sql語句
// 功能, 執(zhí)行sql字符串
// 參數(shù)1: 一個已經(jīng)打開的數(shù)據(jù)庫(代表操作的是哪一個數(shù)據(jù)庫)
// 參數(shù)2: sql語句
// 參數(shù)3: 回調(diào)函數(shù) nil
// 參數(shù)4: 參數(shù)3: 回調(diào)函數(shù)里面的參數(shù)1 nil
// 參數(shù)5: 錯誤信息 nil
return sqlite3_exec(db, sql, nil , nil , nil) == SQLITE_OK
}
數(shù)據(jù)庫的優(yōu)化(大批量插入數(shù)據(jù)的操作)insert綁定參數(shù)
- 如果大批量插入數(shù)據(jù)的話有兩種方案
方案一:sqlite3_step() 準(zhǔn)備語句(執(zhí)行準(zhǔn)備語句)
方案二:sqlite3_exec() sql字符串(執(zhí)行sql語句)
-
優(yōu)化的原理:
- 由于這兩個執(zhí)行函數(shù)苫拍,在執(zhí)行的時候內(nèi)部都會自動開啟一個事務(wù)芜繁,當(dāng)執(zhí)行完畢之后提交事務(wù),整個過程(開啟事務(wù)->提交事務(wù))是非常耗費(fèi)時間(簡單來說就是插入提交绒极,插入提交....)
- 優(yōu)化實(shí)現(xiàn):手動實(shí)現(xiàn)事務(wù)的開啟和提交骏令,那么在函數(shù)內(nèi)部, 就不會自動開啟和提交事務(wù)
方案一的實(shí)現(xiàn):insert綁定參數(shù)和事務(wù)開啟和提交的手動實(shí)現(xiàn)測試插入數(shù)據(jù)的耗時計(jì)算
func insertBind() -> () {
let sql = "insert into t_stu(name, age, score) values (?, ?, ?);"
// 1. 創(chuàng)建"準(zhǔn)備語句"
// 參數(shù)1: 一個打開的數(shù)據(jù)庫
// 參數(shù)2: sql字符串
// 參數(shù)3: 取出參數(shù)2 的長度 3 -1代表自動計(jì)算
// 參數(shù)4: 指向"準(zhǔn)備語句的指針"
// 參數(shù)5: 通過參數(shù)3指定的長度, 取出參數(shù)2, 字符串之后, 剩余的字符串 nil
let db = SQLiteTool.shareInstance.db
var stmt: COpaquePointer = nil
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
print("準(zhǔn)備語句創(chuàng)建失敗")
return
}
// 開啟事務(wù)
SQLiteTool.shareInstance.beginTransaction()
// 測試插入數(shù)據(jù)耗時
for _ in 0..<10000 {
// 2. 綁定數(shù)據(jù)(不同的數(shù)據(jù)類型, 綁定的方法不一樣)
/**
* 參數(shù):
* COpaquePointer:準(zhǔn)備語句
* Int32:綁定的索引 從1開始
* UnsafePointer<Int8>:綁定的值(給 ?位置傳的值)
* Int32:代表, 值取出的長度 -1 自動計(jì)算
* ((UnsafeMutablePointer<Void>) -> Void)!:指向函數(shù)的指針: 參數(shù)的處理方式
*/
// #define SQLITE_STATIC 處理方式: 不對參數(shù)做任何操作(認(rèn)為參數(shù)是一個static)
// #define SQLITE_TRANSIENT 處理方式: 會對參數(shù), 做一個強(qiáng)引用, 然后, 使用完畢之后, 在合適的時候釋放
// 使用這個函數(shù)一定要注意: 需要明確的知道最終的確切類型是什么
let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)
sqlite3_bind_text(stmt, 1, "yang", -1, SQLITE_TRANSIENT)
// 綁定 Int 類型
sqlite3_bind_int(stmt, 2, 18)
// 綁定 -Double 類型
sqlite3_bind_double(stmt, 3, 99)
// 3. 執(zhí)行"準(zhǔn)備語句"
if sqlite3_step(stmt) == SQLITE_DONE {
print("執(zhí)行成功")
}else {
print("執(zhí)行失敗")
}
// 4. 重置"準(zhǔn)備語句"
sqlite3_reset(stmt)
}
// 提交事務(wù)
SQLiteTool.shareInstance.commitTransaction()
// 5. 釋放資源
sqlite3_finalize(stmt)
}