swift -> sqlite3

添加libsqlite3.tbd General -> Linked Frameworks and Libraries -> 添加libsqlite3.tbd

添加橋接 Build Settings -> (搜索 Bridg)Objective-C Bridging Header -> 添加 項(xiàng)目名/Bridge.h

Bridge.h 添加一行如下:

#import

extension String{

/**

將當(dāng)前字符串拼接到cache目錄后面

*/

func cacheDir() -> String{

let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! ?as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

/**

將當(dāng)前字符串拼接到doc目錄后面

*/

func docDir() -> String

{

let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! ?as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

/**

將當(dāng)前字符串拼接到tmp目錄后面

*/

func tmpDir() -> String

{

let path = NSTemporaryDirectory() as NSString

return path.stringByAppendingPathComponent((self as NSString).lastPathComponent)

}

}

打開數(shù)據(jù)庫 :SQLiteManager.shareManager().openDB("sql.sqlite")

關(guān)閉數(shù)據(jù)庫:let bool = closeDB(db)

創(chuàng)建表:let bool = creatTable("T_Class")

查詢:let sql = "SELECT * FROM T_Class;"

let res = SQLiteManager.shareManager().execRecordSQL(sql)

刪除(更新插入修改下sql語句):

let sql = "DELETE FROM T_Class WHERE age IS 10;"

let bool = SQLiteManager.shareManager().execSQL(sql)

子線程執(zhí)行插入數(shù)據(jù)庫:

SQLiteManager.shareManager().execQueueSQL { (manager) -> () in

// 1.編寫SQL語句

let sql = "INSERT INTO T_Person" +

"(name, age)" +

"VALUES" +

"('\\(self.name!)', \\(self.age));"

// 2.執(zhí)行SQL語句

manager.execSQL(sql)

print(NSThread.currentThread())

}

事務(wù)+預(yù)編譯 提高效率:

let manager = SQLiteManager.shareManager()

// 開啟事務(wù)

manager.beginTransaction()

for i in 0..<10000

{

let sql = "INSERT INTO T_Person" +

"(name, age)" +

"VALUES" +

"(?, ?);"

manager.batchExecSQL(sql, args: "yy +\\(i)", 1 + i)

}

// 提交事務(wù)

manager.commitTransaction()

class SQLiteManager: NSObject {

private static let manager: SQLiteManager = SQLiteManager()

/// 單粒

class func shareManager() ->SQLiteManager {

return manager

}

// 數(shù)據(jù)庫對(duì)象

private var db:COpaquePointer = nil

/**

打開數(shù)據(jù)庫

:param: SQLiteName 數(shù)據(jù)庫名稱

*/

func openDB(SQLiteName: String)

{

// 0.拿到數(shù)據(jù)庫的路徑

let path = SQLiteName.docDir()

print(path)

let cPath = path.cStringUsingEncoding(NSUTF8StringEncoding)!

// 1.打開數(shù)據(jù)庫

/*

1.需要打開的數(shù)據(jù)庫文件的路徑, C語言字符串

2.打開之后的數(shù)據(jù)庫對(duì)象 (指針), 以后所有的數(shù)據(jù)庫操作, 都必須要拿到這個(gè)指針才能進(jìn)行相關(guān)操作

*/

// open方法特點(diǎn): 如果指定路徑對(duì)應(yīng)的數(shù)據(jù)庫文件已經(jīng)存在, 就會(huì)直接打開

// ? ? ? ? ? ? ?如果指定路徑對(duì)應(yīng)的數(shù)據(jù)庫文件不存在, 就會(huì)創(chuàng)建一個(gè)新的

if sqlite3_open(cPath, &db) != SQLITE_OK

{

print("打開數(shù)據(jù)庫失敗")

return

}

// 創(chuàng)建一個(gè)串行隊(duì)列

private let dbQueue = dispatch_queue_create("com.xxx.sql", DISPATCH_QUEUE_SERIAL)

/**

子線程執(zhí)行數(shù)據(jù)庫插入操作

- parameter action:閉包

*/

func execQueueSQL(action: (manager: SQLiteManager)->())

{

// 1.開啟一個(gè)子線程

dispatch_async(dbQueue) { () -> Void in

print(NSThread.currentThread())

// 2.執(zhí)行閉包

action(manager: self)

}

}

// 2.創(chuàng)建表

if creatTable("T_Class")

{

print("創(chuàng)建表成功")

}else

{

print("創(chuàng)建表失敗")

}

}

/// 自定義一個(gè)SQLITE_TRANSIENT, 覆蓋系統(tǒng)的

private let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)

// MARK: - 預(yù)編譯 + 事務(wù)可以提高效率

func batchExecSQL(sql:String, args: CVarArgType...) -> Bool

{

// 1.將SQL語句轉(zhuǎn)換為C語言

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 2.預(yù)編譯SQL語句

var stmt: COpaquePointer = nil

if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK

{

print("預(yù)編譯失敗")

sqlite3_finalize(stmt)

return false

}

// 3.綁定數(shù)據(jù)

var index:Int32 = 1

for objc in args

{

if objc is Int

{

// ? ? ? ? ? ? ? ?print("通過int方法綁定數(shù)據(jù) \\(objc)")

// 第二個(gè)參數(shù)就是SQL中('?', ?)的位置, 注意: 從1開始

sqlite3_bind_int64(stmt, index, sqlite3_int64(objc as! Int))

}else if objc is Double

{

// ? ? ? ? ? ? ? ?print("通過Double方法綁定數(shù)據(jù) \\(objc)")

sqlite3_bind_double(stmt, index, objc as! Double)

}else if objc is String

{

// ? ? ? ? ? ? ? ?print("通過Text方法綁定數(shù)據(jù) \\(objc)")

let text = objc as! String

let cText = text.cStringUsingEncoding(NSUTF8StringEncoding)!

// 第三個(gè)參數(shù): 需要綁定的字符串, C語言

// 第四個(gè)參數(shù): 第三個(gè)參數(shù)的長度, 傳入-1系統(tǒng)自動(dòng)計(jì)算

// 第五個(gè)參數(shù): OC中直接傳nil, 但是Swift傳入nil會(huì)有大問題

/*

typedef void (*sqlite3_destructor_type)(void*);

#define SQLITE_STATIC ? ? ?((sqlite3_destructor_type)0)

#define SQLITE_TRANSIENT ? ((sqlite3_destructor_type)-1)

第五個(gè)參數(shù)如果傳入SQLITE_STATIC/nil, 那么系統(tǒng)不會(huì)保存需要綁定的數(shù)據(jù), 如果需要綁定的數(shù)據(jù)提前釋放了, 那么系統(tǒng)就隨便綁定一個(gè)值

第五個(gè)參數(shù)如果傳入SQLITE_TRANSIENT, 那么系統(tǒng)會(huì)對(duì)需要綁定的值進(jìn)行一次copy, 直到綁定成功之后再釋放

*/

sqlite3_bind_text(stmt, index, cText, -1, SQLITE_TRANSIENT)

}

index += 1

}

// 4.執(zhí)行SQL語句

if sqlite3_step(stmt) != SQLITE_DONE

{

print("執(zhí)行SQL語句失敗")

return false

}

// 5.重置STMT

if sqlite3_reset(stmt) != SQLITE_OK

{

print("重置失敗")

return false

}

// 6.關(guān)閉STMT

// 注意點(diǎn): 只要用到了stmt, 一定要關(guān)閉

sqlite3_finalize(stmt)

return true

}

/**

關(guān)閉數(shù)據(jù)庫

- parameter db: 數(shù)據(jù)庫

*/

func closeDB(db: COpaquePointer) -> Bool{

if sqlite3_close(db) == SQLITE_OK {

return true

}

return false

}

// MARK: - 事務(wù)相關(guān) (可以提高性能)

// 1.開啟事務(wù)

func beginTransaction()

{

execSQL("BEGIN TRANSACTION")

}

// 2.提交事務(wù)

func commitTransaction()

{

execSQL("COMMIT TRANSACTION")

}

// 3.回滾

func rollbackTransaction()

{

execSQL("ROLLBACK TRANSACTION")

}

//創(chuàng)建表

func creatTable(table: String) -> Bool

{

// 1.編寫SQL語句

let sql = "CREATE TABLE IF NOT EXISTS \\(table)( \\n" +

"id INTEGER PRIMARY KEY AUTOINCREMENT, \\n" +

"name TEXT, \\n" +

"age INTEGER \\n" +

"); \\n"

// 2.執(zhí)行SQL語句

return execSQL(sql)

}

/**

執(zhí)行除查詢以外的SQL語句

:param: sql 需要執(zhí)行的SQL語句

:returns: 是否執(zhí)行成功 true執(zhí)行成功 false執(zhí)行失敗

*/

func execSQL(sql: String) -> Bool

{

// 0.將Swift字符串轉(zhuǎn)換為C語言字符串

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 在SQLite3中, 除了查詢意外(創(chuàng)建/刪除/新增/更新)都使用同一個(gè)函數(shù)

/*

1. 已經(jīng)打開的數(shù)據(jù)庫對(duì)象

2. 需要執(zhí)行的SQL語句, C語言字符串

3. 執(zhí)行SQL語句之后的回調(diào), 一般傳nil

4. 是第三個(gè)參數(shù)的第一個(gè)參數(shù), 一般傳nil

5. 錯(cuò)誤信息, 一般傳nil

*/

if sqlite3_exec(db, cSQL, nil, nil, nil) != SQLITE_OK

{

return false

}

return true

}

/**

查詢所有的數(shù)據(jù)

:returns: 查詢到的字典數(shù)組

*/

func execRecordSQL(sql: String) ->[[String: AnyObject]]

{

// 0.將Swift字符串轉(zhuǎn)換為C語言字符串

let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!

// 1.準(zhǔn)備數(shù)據(jù)

// 準(zhǔn)備: 理解為預(yù)編譯SQL語句, 檢測里面是否有錯(cuò)誤等等, 它可以提供性能

/*

1.已經(jīng)開打的數(shù)據(jù)庫對(duì)象

2.需要執(zhí)行的SQL語句

3.需要執(zhí)行的SQL語句的長度, 傳入-1系統(tǒng)自動(dòng)計(jì)算

4.預(yù)編譯之后的句柄, 已經(jīng)要想取出數(shù)據(jù), 就需要這個(gè)句柄

5. 一般傳nil

*/

var stmt: COpaquePointer = nil

if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK

{

print("準(zhǔn)備失敗")

}

// 準(zhǔn)備成功

var records = [[String: AnyObject]]()

// 2.查詢數(shù)據(jù)

// sqlite3_step代表取出一條數(shù)據(jù), 如果取到了數(shù)據(jù)就會(huì)返回SQLITE_ROW

while sqlite3_step(stmt) == SQLITE_ROW

{

// 獲取一條記錄的數(shù)據(jù)

let record = recordWithStmt(stmt)

// 將當(dāng)前獲取到的這一條記錄添加到數(shù)組中

records.append(record)

}

// 注意點(diǎn): 只要用到了stmt, 一定要關(guān)閉

sqlite3_finalize(stmt)

// 返回查詢到的數(shù)據(jù)

return records

}

/**

獲取一條記錄的值

:param: stmt 預(yù)編譯好的SQL語句

:returns: 字典

*/

private func recordWithStmt(stmt: COpaquePointer) ->[String: AnyObject]

{

// 2.1拿到當(dāng)前這條數(shù)據(jù)所有的列

let count = sqlite3_column_count(stmt)

// ? ? ? ? ? ?print(count)

// 定義字典存儲(chǔ)查詢到的數(shù)據(jù)

var record ?= [String: AnyObject]()

for index in 0..

{

// 2.2拿到每一列的名稱

let cName = sqlite3_column_name(stmt, index)

let name = String(CString: cName, encoding: NSUTF8StringEncoding)!

// ? ? ? ? ? ? ? ?print(name)

// 2.3拿到每一列的類型 SQLITE_INTEGER

let type = sqlite3_column_type(stmt, index)

// ? ? ? ? ? ? ? ?print("name = \\(name) , type = \\(type)")

switch type

{

case SQLITE_INTEGER:

// 整形

let num = sqlite3_column_int64(stmt, index)

record[name] = Int(num)

case SQLITE_FLOAT:

// 浮點(diǎn)型

let double = sqlite3_column_double(stmt, index)

record[name] = Double(double)

case SQLITE3_TEXT:

// 文本類型

let cText = UnsafePointer(sqlite3_column_text(stmt, index))

let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!

record[name] = text

case SQLITE_NULL:

// 空類型

record[name] = NSNull()

print(record)

default:

// 二進(jìn)制類型 SQLITE_BLOB

// 一般情況下, 不會(huì)往數(shù)據(jù)庫中存儲(chǔ)二進(jìn)制數(shù)據(jù)

print("")

}

}

return record

}

}

SQLite函數(shù)總結(jié)

1.打開數(shù)據(jù)庫

int sqlite3_open(

const char *filename, ? // 數(shù)據(jù)庫的文件路徑

sqlite3 **ppDb ? ? ? ? ?// 數(shù)據(jù)庫實(shí)例

);

2.執(zhí)行任何SQL語句

int sqlite3_exec(

sqlite3*, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 一個(gè)打開的數(shù)據(jù)庫實(shí)例

const char *sql, ? ? ? ? ? ? ? ? ? ? ? ? ? // 需要執(zhí)行的SQL語句

int (*callback)(void*,int,char**,char**), ?// SQL語句執(zhí)行完畢后的回調(diào)

void *, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 回調(diào)函數(shù)的第1個(gè)參數(shù)

char **errmsg ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 錯(cuò)誤信息

);

3.檢查SQL語句的合法性(查詢前的準(zhǔn)備)

int sqlite3_prepare_v2(

sqlite3 *db, ? ? ? ? ? ?// 數(shù)據(jù)庫實(shí)例

const char *zSql, ? ? ? // 需要檢查的SQL語句

int nByte, ? ? ? ? ? ? ?// SQL語句的最大字節(jié)長度

sqlite3_stmt **ppStmt, ?// sqlite3_stmt實(shí)例,用來獲得數(shù)據(jù)庫數(shù)據(jù)

const char **pzTail

);

4.查詢一行數(shù)據(jù)

int sqlite3_step(sqlite3_stmt*); // 如果查詢到一行數(shù)據(jù),就會(huì)返回SQLITE_ROW

5.利用stmt獲得某一字段的值(字段的下標(biāo)從0開始)

double sqlite3_column_double(sqlite3_stmt*, int iCol); ?// 浮點(diǎn)數(shù)據(jù)

int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型數(shù)據(jù)

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 長整型數(shù)據(jù)

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二進(jìn)制文本數(shù)據(jù)

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); ?// 字符串?dāng)?shù)據(jù)

SQLite語句

/*簡單約束*/

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER);

CREATE TABLE IF NOT EXISTS t_student(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER DEFAULT 1);

/*分頁*/

SELECT * FROM t_student ORDER BY id ASC LIMIT 30, 10;

/*排序*/

SELECT * FROM t_student WHERE score > 50 ORDER BY age DESC;

SELECT * FROM t_student WHERE score < 50 ORDER BY age ASC , score DESC;

/*計(jì)量*/

SELECT COUNT(*) FROM t_student WHERE age > 50;

/*別名*/

SELECT name as myName, age as myAge, score as myScore FROM t_student;

SELECT name myName, age myAge, score myScore FROM t_student;

SELECT s.name myName, s.age myAge, s.score myScore FROM t_student s WHERE s.age > 50;

/*查詢*/

SELECT name, age, score FROM t_student;

SELECT * FROM t_student;

/*修改指定數(shù)據(jù)*/

UPDATE t_student SET name = 'MM' WHERE age = 10;

UPDATE t_student SET name = 'WW' WHERE age is 7;

UPDATE t_student SET name = 'XXOO' WHERE age < 20;

UPDATE t_student SET name = 'NNMM' WHERE age < 50 and score > 10;

/*刪除數(shù)據(jù)*/

DELETE FROM t_student;

/*更新數(shù)據(jù)*/

UPDATE t_student SET name = 'LNJ';

/*插入數(shù)據(jù)*/

INSERT INTO t_student(age, score, name) VALUES ('28', 100, 'jonathan');

INSERT INTO t_student(name, age) VALUES ('lee', '28');

INSERT INTO t_student(score) VALUES (100);

/*插入數(shù)據(jù)*/

INSERT INTO t_student(name, age, score) VALUES ('lee', '28', 100);

/*添加主鍵*/

CREATE TABLE IF NOT EXISTS t_student (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, score REAL);

/*添加主鍵*/

CREATE TABLE IF NOT EXISTS t_student (id INTEGER, name TEXT, age INTEGER, score REAL, PRIMARY KEY(id));

/*刪除表*/

DROP TABLE IF EXISTS t_student;

/*創(chuàng)建表*/

CREATE TABLE IF NOT EXISTS t_student(id INTEGER , name TEXT, age , score REAL);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容