因爲SQLite3是由C語言編寫的,包含在C庫中,所以Swift要使用源生的SQLite3需要Swift-OC混編
此處不再重複SQL可視化工具和如何添加SQLite3,如有需要,可以參考《iOS SQLite3 “增刪改查”(Objective-C)》
創建完工程,並已添加SQLite3,則創建橋接文件Bridging-Header,導入sqlite3.h
跟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表示成功)
到這裏,我們可以通過SQLite可視化工具查看一下,剛剛的兩個函數有沒有按照我們的想法執行
接下來更新數據
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)
}
}
}
查詢結果
跟SQLite Professional中得截圖對比一下
在調試過程中,總是會不可避免的出現問題,所以儘量打印返回值對照錯誤原因去解決問題
#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 */