sqlite.swift應用簡介

    SQLite3是一款非常輕便易用並且開源的嵌入式數據庫,而SQLite3官方所提供的API接口是用C來提供的,如果用swift進行macOS或是iOS開發的話,就會很不方便,因此有一個國外的大神用swift封裝了SQLite提供的API,並且分享在了GitHub上,稱之爲sqlite.swift,並且最新版本也使用了swift3的語法。原版的說明文檔在此:https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#setters,不過對於像我一樣英語不太好的朋友來說,可能閱讀起來是個障礙。所以這篇文章就來介紹一下sqlite.swift的一些常用的功能和用法。

1.安裝

    首先是導入,官方介紹了4種導入的方法,最簡單(也是最手動的)其實是最後一種,就是直接下載然後手動導入,這種導入方法我嘗試過,開發時沒有什麼問題,但是在發佈打包的時候無論如何都不能運行打包後的app,不知道究竟是哪裏的設置沒有搞對。所以本人推薦的是使用CocoaPods進行安裝導入工程,這樣做在工程開發完畢後打包出來的app親測可用的。關於CocoaPods的安裝方法這裏不多做贅述,網上的教程非常多,如果有疑問的話歡迎留言討論。

    那麼第一步,我們需要建立一個工程(iOS或macOS),然後打開終端,進入到項目工程的根目錄下,創建一個文件叫"Podfile":

然後用一個你喜歡的文本編輯器打開它,習慣用終端的朋友當然也可以用vim或者nano直接打開。打開之後在文件中寫入:

use_frameworks!

target 'sqlite_test' do
    pod 'SQLite.swift', '~> 0.11.3'
end
其中的“sqlite_test”換成你實際的工程名稱,然後在終端執行:

pod install --repo-update
等待安裝完畢(如果是初次安裝需要一段時間從網上下載),如果在整個運行過程中沒有出現紅色的文字段,就說明安裝成功了


然後在你的項目中會多了一些文件,其中有一個擴展名是xcworkspace的,我們以後打開工程就用它。


2.創建數據庫

如果要使用sqlite庫中的內容,必須在程序文件前引入該庫:
import SQLite
然後連接數據庫:
try? dbCon = Connection("/test/db1.sqlite3", readonly: false)
其中第一個參數是數據庫的路徑,第二個參數是制定數據庫是否爲只讀,如果是false的話可以省略

3.執行SQL語句

    雖然sqlite.swift用swift語言封裝了絕大多數的數據庫功能,但是有的時候我們還是需要自己來執行SQL語句的,執行SQL語句分爲兩種情況,一種是命令語句,比如說建立表格,插入數據,或者是打開外鍵約束功能之類的,我們僅僅是要執行一句指令,而不需要得到什麼數據,如果是這種類型的語句的話,要用下面這個方法:
try? dbCon?.execute("PRAGMA foreign_key = ON;")
函數的參數就寫你要執行的SQL語句就可以了。
    還有一種情況是希望得到返回值的,比如說查詢語句等等,這個時候就要用下面這個方法:
let result = try? dbCon?.prepare("SELECT * FROM tb1;")
它會得到查詢語句的返回值,至於這個返回值怎麼時候,請參考後面關於數據查詢部分的內容。

4.建立表格

    建立表格的時候,需要對每一個數據項的屬性來進行指定,比如說主鍵,外鍵,默認值等等,在介紹這些之前,我們需要先認識一個數據類型:
Expression<T>
這是後面經常要用到的一個數據類型,它用來表示表的一個數據項,當然也可以表示某一條記錄的某一個數據項,T爲該屬性的類型,如果指定了一個可選類型,那麼表示該數據項可以爲NULL,否則不可以爲NULL,這裏支持的類型和SQLite中類型的對應關係如下:

swift SQLite
Int INTEGER
Double REAL
String TEXT
nil NULL
這裏要注意的是,Int對應的是INTEGER而不是INT,因此如果你的主鍵是Int類型的話,是默認被設置爲自增型的。
    比如說我要表示一個名爲“name”的數據項,它是String類型的,我就應該寫成:
Expression<String>("name")
    下一個要介紹的類型是Expressible,這是一個結構體,實現還是比較複雜的,但是我們基本上可以理解成Expression<Any>,所以如果要見到這個類型,就知道是要傳入Expression的一個實例就好了。
    接下來是TableBuilder類型,本質也比較複雜,不過可以理解成[Expressible]就可以了,這個類型並不常用,只是在建表的時候用得到。
    終於說到建表了,建表的方法如下:
try? dbCon?.run(Table("test").create(ifNotExists: true, block:{(tb) in
            tb.column(Expression<String>("name"))
            tb.column(Expression<String?>("note"))
        }))
Table是一個結構體,傳入字符串作爲表的名稱,create方法有很多重載,這裏的第一個參數如果爲true,就表示如果該表已經存在就無視該動作,如果爲false可以省略,這時如果表已存在就會拋出異常(由於本文主要是說明數據庫的使用,這裏所有的異常都沒有理睬,所以用了try?語法,真實開發時應該給予考慮),第二個參數是一個(TableBuilder) -> ()類型的閉包,在閉包中對錶格的每一個數據項進行設置,column方法也有很多重載,常用的有以下幾個:
public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil)
public func column<V : Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil)
可以用來制定UNIQUE,CHECK,DEFAULT,PRIMARY KEY屬性,與直接使用SQLite數據庫相同,不再贅述。在次強調,NOT NULL屬性是默認添加的,如果不想添加該屬性,需要在Expression的類型中設置可選類型

4.1複合主鍵

     如果表中有複合主鍵,則不能再使用上面的方法,需要使用下面的方法:
tb.primaryKey(Expression<String>("name"), Expression<String>("property"))
調用primaryKey方法,傳入若干個Expression,就可以把它們設置成複合主鍵。

4.2外鍵

    外鍵的設置需要制定本表中個一個屬性,還要制定參照表和參照表中的屬性,例如:
tb.foreignKey(Expression<String>("username"), references: Table("user"), Expression<String>("username"), update: .cascade, delete: .cascade)
    相當於如下的SQL語句:
FOREIGN KEY(username) REFERENCES user(username) ON UPDATE cascade ON DELETE cascade;
最後兩個參數如果去掉的話,有外鍵約束的數據記錄將不允許更改或刪除。
    如果是複合外鍵,只需要把第一個參數和第三個參數改成Expression組成的元組就可以了,比如說:
tb.foreignKey((Expression<String>("forDevice"), Expression<String>("type")), references: Table("device"),( Expression<String>("name"), Expression<String>("property")), update: .cascade, delete: .cascade)
道理與單個的外鍵相同。
    這裏還有一個要強調的地方(這其實是SQLite數據庫的特點而不是sqlite.swift庫的特點,但是經常容易碰到所以強調一下)就是,如果外鍵約束設置錯誤的話,在建表的時候是不會拋出異常的,而在插入數據的時候回有外鍵設置異常的報錯,很多人在insert的時候發現了報錯就以爲一定是insert語句的問題,這並不一定,因爲有可能是建表時就有的錯誤,但是它只會在操作數據記錄的時候纔會報錯(不知道爲什麼這樣設計,很坑)。一個比較常見的外鍵綁定錯誤就是,外鍵在參照表中必須是UNIQUE屬性,也就是說,它要麼有UNIQUE屬性修飾,要麼是主鍵。而如果它僅僅是複合主鍵中的一部分,並且沒有UNIQUE修飾的話,是不能成爲參照的外鍵的(這點超級超級超級坑),因爲它不是主鍵的全部,所以是可以有重複的。如果你希望參照的屬性是複合主鍵的話,那你就必須用複合外鍵參照整個複合主鍵纔可以。總之就是,一定要確定它是不是唯一的,如果不是唯一屬性的,不可以被參照。

5.插入記錄

    先介紹一個類型,Setter類型,實現比較複雜,簡化以後就是如下的一個結構
Expression<T> <- T

顯示一個Expression,然後一個小於號和一個減號,也就是個向左的箭頭,右邊是一個對應類型的表達式,比如說下面這就是合法的表達式:

Expression<Int>("id") <- 1
Expression<String>("name") <- "admin"
insert方法要求的參數就是一個Setter類型,用法如下:
try? dbCon?.run(Table("user").insert(Expression<String>("name") <- "admin"))
insert方法還可傳入多個Setter,往後繼續寫就可以插入多個數據項:
try? dbCon?.run(Table("user").insert(Expression<String>("name") <- "admin"), Expression<Int>("id") <- 5)
不過就是要注意如果是非空屬性的話,必須得一次性寫全纔可以,不能分多個insert語句插入

6.查詢記錄

    查詢記錄要用到的類型是Expression<Bool>類型,它可以通過兩個同屬性的Expression<T>運算獲得,或者是一個Expression和一個常數獲得,比如說

Expression<Int>("value") >= 5
就會返回一個Expression<Bool>類型的數據,所以選擇一個表的某些複合條件的行,用到filter函數,傳入的參數是一個Expression<Bool>類型的數據,例如:

let tb = Table("user").filter(Expression<Int>("id") >= 5)
相當於SQL語句:

SELECT * FROM user WHERE id >= 5;
如果選列的話,要用到select 函數,傳入一個或若干個Expression,比如說:

let result = Table("user").select(Expression<String>("name"))
相當於SQL語句:
SELECT name FROM user;
當然,上面兩個語句可以疊加使用,比如:

let result = Table("user").select(Expression<String>("name")).filter(Expression<Int>("id") > 8)
相當於SQL語句:

SELECT name FROM user WHERE id > 8;

    拿到的結果是一個AnySequence<Row>?類型的數據,這個類型比較討厭,因爲你不能通過下角標直接找到第幾行第幾行的數據,必須用遍歷語句來查找,而且還是一個可選類型,要注意判斷是否爲空然後解包,遍歷中得到的是一個Row類型的數據,可以通過get方法獲得對應的數據,比如下面的例子:

for row in result! {
    let name = row.get(Expression<String>("name"))
    let id = row.get(Expression<Int>("id"))
    Swift.print("name:" + name + "id:\(id)")
}

7.更改記錄

    更改記錄其實就是查詢和添加記錄的組合,用到了update函數,不再過多說明,直接看例子:

dbCon?.run(Table("user").filter(Expression<Int>("id") > 5 && Expression<String>("sex") == "male").update(Expression<String>("name") <- "haha"))
相當於SQL語句:
UPDATE user SET name = "haha" WHERE id > 5 and sex = "male";

8.刪除記錄

    刪除記錄用法與更改記錄相同,用到了selete函數,例如:

dbCon?.run(Table("user").fiilter(Expression("id") < 6).delete())
相當於SQL語句:

DELETE FROM user WHERE id < 6;

9.其他功能

    其實這些用法都與SQL語句非常的相似,所以用起來也很得心應手,drop函數用於刪除表,alter函數用於更改表結構,等等的功能,只需要稍微看一下函數聲明,一定就會用了。

    關於sqlite.swift的簡單介紹就到這裏,如果你有問題或者好的簡介,非常歡迎在下面留言,我們共同來探討,共同學習和進步。







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