iOS 源生SQLite3 “增刪改查”(Swift-OC混編)

因爲SQLite3是由C語言編寫的,包含在C庫中,所以Swift要使用源生的SQLite3需要Swift-OC混編
此處不再重複SQL可視化工具和如何添加SQLite3,如有需要,可以參考《iOS SQLite3 “增刪改查”(Objective-C)
創建完工程,並已添加SQLite3,則創建橋接文件Bridging-Header,導入sqlite3.h
Bridge
跟OC一樣,需要創建一個全局的句柄

 var db: COpaquePointer = nil

由於Swift中沒有C語言的指針概念,所以這裏不能使用

static sqlite3 * db = nil

而我們不知道sqlite3在Swift是什麼類型,因爲Swift沒有這個東西,這是C語言提供的,所以只能用一個模糊不清的概念,使用一個前置聲明的指針COpaquePointer。關於COpaquePointer的資料請看《在Swift中使用歷史遺留的C API
然後按部就班:創建表格——插入數據——修改數據——刪除數據——查看數據
打開數據庫並創建表格

func openDB() {
        /*
         directory 目錄類型 比如Documents目錄 就是NSDocumentDirectory
         domainMask 在iOS的程序中這個取NSUserDomainMask
         expandTilde YES,表示將~展開成完整路徑
         lastObject 取NSSearchPathForDirectoriesInDomains數組最後一個元素
         */
//        let test: NSArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,  YES)
        let test: NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true)
        let fileName = (test.lastObject! as! String)+"/"+"DB_ichampion.sqlite"
        print("fileName:",fileName);
        //打開數據庫 如果沒有打開的數據庫就建立一個
        //第一個參數是數據庫的路徑 注意要轉換爲c的字符串
        if (sqlite3_open(fileName, &db) == SQLITE_OK) {
            print("打開數據庫成功")
            //打開數據庫成功後建立數據庫內的表
            //操作命令的字符串
            //注意SQL語句結束處有 ; 號
            let sql = "create table if not exists Table_ichampion (id integer primary key autoincrement,name text,age intger);"

            if(sqlite3_exec(db,sql.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil)
                == SQLITE_OK)
            {
                print("建表成功")
            }else{
                print("建表失敗")
            }
        }else{
            print("打開數據庫失敗")
        }
    }

插入數據

func insertDB() {
        let sql = "insert into Table_ichampion(id,name,age) values(1,'Zhan',18);"
        print("sql",sqlite3_exec(db, sql.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil))

        let sql1 = "insert into Table_ichampion(id,name,age) values(3,'Michael',8);"
        print("sql1",sqlite3_exec(db, sql1.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil))

        let sql2 = "insert into Table_ichampion values(NULL,'abc',6);"
        print("sql2",sqlite3_exec(db, sql2.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil))

        let tableName = "Table_ichampion"
        let Name = "name"
        let Age = "age"
        let NameValue = "abcd"
        let AgeValue = 3

        let sql3 = "INSERT INTO " + tableName + "(id," + Name + "," + Age + ") VALUES(" + String(5) + ",'" + NameValue + "'," +  String(AgeValue) + ");"
        print("sql3",sqlite3_exec(db, sql3.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil))
    }

插入數據這裏,我們採用打印返回值的寫法,可以看到程序執行是否成功(返回值爲0表示成功)
insert
到這裏,我們可以通過SQLite可視化工具查看一下,剛剛的兩個函數有沒有按照我們的想法執行
sql1
接下來更新數據

func updateDB() {
        let sql = "update Table_ichampion set name = 'xyz' where id = 5;"
        print(sqlite3_exec(db, sql.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil))
    }

再刪除一條記錄

func deleteDB() {
        let sql = "DELETE FROM Table_ichampion WHERE name = 'abc';"
        if (sqlite3_exec(db, sql.cStringUsingEncoding(NSUTF8StringEncoding)!, nil, nil, nil) == SQLITE_OK) {
            print("OK!")
        }
    }

做完這兩步,我們直接寫查看部分,看看abc這條記錄是否刪除,abcd是否改名爲xyz
這裏寫了兩個查詢方式,一個是整張表格查詢,一個是單條記錄查詢

func selectDB() {
        let sql = "select * from Table_ichampion"
        var stmt : COpaquePointer = nil
        if (sqlite3_prepare_v2(db, sql.cStringUsingEncoding(NSUTF8StringEncoding)!, -1, &stmt, nil) == SQLITE_OK) {
            while (sqlite3_step(stmt) == SQLITE_ROW) {

                let id = UnsafePointer<CChar>(sqlite3_column_text(stmt, 0))
                let idStr = String.fromCString(id)

                let name = UnsafePointer<CChar>(sqlite3_column_text(stmt, 1))
                let nameStr = String.fromCString(name)

                let age = UnsafePointer<CChar>(sqlite3_column_text(stmt, 2))
                let ageStr = String.fromCString(age)

                let info = idStr! + " " + nameStr! + " " + ageStr!
                print("ALL -- ",info)
            }
        }
        let sql1 = "SELECT * FROM Table_ichampion WHERE name = 'Zhan';"
        if (sqlite3_prepare_v2(db, sql1.cStringUsingEncoding(NSUTF8StringEncoding)!, -1, &stmt, nil) == SQLITE_OK) {
            while (sqlite3_step(stmt) == SQLITE_ROW) {

                let id = UnsafePointer<CChar>(sqlite3_column_text(stmt, 0))
                let idStr = String.fromCString(id)

                let name = UnsafePointer<CChar>(sqlite3_column_text(stmt, 1))
                let nameStr = String.fromCString(name)

                let age = UnsafePointer<CChar>(sqlite3_column_text(stmt, 2))
                let ageStr = String.fromCString(age)

                let info = idStr! + " " + nameStr! + " " + ageStr!
                print("Zhan -- ",info)
            }
        }
    }

查詢結果
select
跟SQLite Professional中得截圖對比一下
SQL2
在調試過程中,總是會不可避免的出現問題,所以儘量打印返回值對照錯誤原因去解決問題

#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* Database is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT  19   /* Abort due to constraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Auxiliary database format error */
#define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* File opened that is not a database file */
#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
/* end-of-error-codes */

源碼:iOS源生SQLite3基本操作(Swift-OC混編)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章