第十二篇、Swift_Sqlite的使用


 

import UIKit

class SQLiteManager: NSObject {

    private static let manager: SQLiteManager = SQLiteManager()
    /// 單粒
    class func shareManager() ->SQLiteManager {
        return manager
    }
    
    // 數據庫對象
    private var db:COpaquePointer = nil
    
    // 創建一個串行隊列
    private let dbQueue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_SERIAL)
    
    func execQueueSQL(action: (manager: SQLiteManager)->())
    {
        // 1.開啟一個子線程
        dispatch_async(dbQueue) { () -> Void in
            print(NSThread.currentThread())
            // 2.執行閉包
            action(manager: self)
        }
    }
    
    /**
    打開數據庫
    
    :param: SQLiteName 數據庫名稱
    */
    func openDB(SQLiteName: String)
    {
        // 0.拿到數據庫的路徑
        let path = SQLiteName.docDir()
        print(path)
        let cPath = path.cStringUsingEncoding(NSUTF8StringEncoding)!
        // 1.打開數據庫
        /*
        1.需要打開的數據庫文件的路徑, C語言字符串
        2.打開之后的數據庫對象 (指針), 以后所有的數據庫操作, 都必須要拿到這個指針才能進行相關操作
        */
        // open方法特點: 如果指定路徑對應的數據庫文件已經存在, 就會直接打開
        //              如果指定路徑對應的數據庫文件不存在, 就會創建一個新的
        if sqlite3_open(cPath, &db) != SQLITE_OK
        {
            print("打開數據庫失敗")
            return
        }
        
        // 2.創建表
        if creatTable()
        {
            print("創建表成功")
        }else
        {
            print("創建表失敗")
        }
    }
    
    private func creatTable() -> Bool
    {
        // 1.編寫SQL語句
        // 建議: 在開發中編寫SQL語句, 如果語句過長, 不要寫在一行
        // 開發技巧: 在做數據庫開發時, 如果遇到錯誤, 可以先將SQL打印出來, 拷貝到PC工具中驗證之后再進行調試
        let sql = "CREATE TABLE IF NOT EXISTS T_Person( \n" +
        "id INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
        "name TEXT, \n" +
        "age INTEGER \n" +
        "); \n"
//        print(sql)
        // 2.執行SQL語句
        return execSQL(sql)
    }
    
    /**
    執行除查詢以外的SQL語句
    
    :param: sql 需要執行的SQL語句
    
    :returns: 是否執行成功 true執行成功 false執行失敗
    */
    func execSQL(sql: String) -> Bool
    {
        // 0.將Swift字符串轉換為C語言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 在SQLite3中, 除了查詢意外(創建/刪除/新增/更新)都使用同一個函數
        /*
        1. 已經打開的數據庫對象
        2. 需要執行的SQL語句, C語言字符串
        3. 執行SQL語句之后的回調, 一般傳nil
        4. 是第三個參數的第一個參數, 一般傳nil
        5. 錯誤信息, 一般傳nil
        */
        if sqlite3_exec(db, cSQL, nil, nil, nil) != SQLITE_OK
        {
            return false
        }
        return true
    }
    
    /**
    查詢所有的數據
    :returns: 查詢到的字典數組
    */
    func execRecordSQL(sql: String) ->[[String: AnyObject]]
    {
        // 0.將Swift字符串轉換為C語言字符串
        let cSQL = sql.cStringUsingEncoding(NSUTF8StringEncoding)!
        
        // 1.准備數據
        // 准備: 理解為預編譯SQL語句, 檢測里面是否有錯誤等等, 它可以提供性能
        /*
        1.已經開打的數據庫對象
        2.需要執行的SQL語句
        3.需要執行的SQL語句的長度, 傳入-1系統自動計算
        4.預編譯之后的句柄, 已經要想取出數據, 就需要這個句柄
        5. 一般傳nil
        */
        var stmt: COpaquePointer = nil
        if sqlite3_prepare_v2(db, cSQL, -1, &stmt, nil) != SQLITE_OK
        {
            print("准備失敗")
        }
        
        // 准備成功
        var records = [[String: AnyObject]]()
        
        // 2.查詢數據
        // sqlite3_step代表取出一條數據, 如果取到了數據就會返回SQLITE_ROW
        while sqlite3_step(stmt) == SQLITE_ROW
        {
            // 獲取一條記錄的數據
            let record = recordWithStmt(stmt)
            // 將當前獲取到的這一條記錄添加到數組中
            records.append(record)
        }
        
        // 返回查詢到的數據
        return records
    }
    
    /**
    獲取一條記錄的值
    
    :param: stmt 預編譯好的SQL語句
    
    :returns: 字典
    */
    private func recordWithStmt(stmt: COpaquePointer) ->[String: AnyObject]
    {
        // 2.1拿到當前這條數據所有的列
        let count = sqlite3_column_count(stmt)
        //            print(count)
        // 定義字典存儲查詢到的數據
        var record  = [String: AnyObject]()
        
        for index in 0..<count
        {
            // 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:
                // 浮點型
                let double = sqlite3_column_double(stmt, index)
                record[name] = Double(double)
            case SQLITE3_TEXT:
                // 文本類型
                let cText = UnsafePointer<Int8>(sqlite3_column_text(stmt, index))
                let text = NSString(CString: cText, encoding: NSUTF8StringEncoding)!
                record[name] = text
            case SQLITE_NULL:
                // 空類型
                record[name] = NSNull()
            default:
                // 二進制類型 SQLITE_BLOB
                // 一般情況下, 不會往數據庫中存儲二進制數據
                print("")
            }
        }
        return record
    }
    
}

 

使用事務插入數據:

       let manager = SQLiteManager.shareManager()
        
        // 開啟事務
        manager.beginTransaction()
        
        for i in 0..<10000
        {
            let p = Person(dict: ["name": "zs + \(i)", "age": 3 + i])
            p.insertPerson()
            
            if i == 1000
            {
                manager.rollbackTransaction()
                // 注意點: 回滾之后一定要跳出循環停止更新
                break
            }
        }
        
        // 提交事務
        manager.commitTransaction()

 

預編譯綁定:

    //1、打開數據庫  
    sqlite3 *db = [self sqlite3_open_database];  
    //2、建立預編譯語句對象並編譯  
    charchar *sql = "INSERT INTO student(name,age) VALUES(?,?)";//?為占位符,代表此處將來用變量值替換  
    //2.1、准備預編譯語句對象  
    sqlite3_stmt *stmt = NULL;  
    //2.2、預編譯sql語句  
    int result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);  
    //2.3、預編譯成功,綁定值  
    if (result == SQLITE_OK) {  
        //綁定界面數據到預編譯sql語句中  
        sqlite3_bind_text(stmt, 1, [self.txtName.text UTF8String], -1, NULL);  
        sqlite3_bind_int(stmt, 2, [self.txtAge.text intValue]);  
        //3、執行預編譯語句對象,4、使用結果  
        result = sqlite3_step(stmt);  
        if (result == SQLITE_DONE) {  
            [self myAlert:@"插入數據成功!"];  
        } else {  
            [self myAlert:@"插入數據失敗!"];  
        }  
    }  
    //5、銷毀預編譯語句對象,關閉數據庫  
    sqlite3_finalize(stmt);  
    sqlite3_close(db); 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM