Sqlite全面學習(一)
官網 SQLite是一款輕型的資料庫,是關係型資料庫(RDBMS)管理系統,它包含在一個相對小的C庫中。目前在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式裝置中,可能只需要幾百K的記憶體就夠了。它能夠支援Windows/Linux/Unix/Android/IOS等等主流的作業系統,同時能夠跟很多程式語言相結合,比如 Tcl、C#、PHP、Java等,還有ODBC介面,同樣比起Mysql、PostgreSQL這兩款開源的世界著名資料庫管理系統來講,它的處理速度比他們都快。
Sqlite命令分類:
(DDL)資料定義語言:
CMD | Description |
---|---|
CREATE | 建立一個新的表,一個表的檢視,或者資料庫中的其他物件。 |
ALTER | 修改資料庫中的某個已有的資料庫物件,比如一個表。 |
DROP | 刪除整個表,或者表的檢視,或者資料庫中的其他物件。 |
(DML)資料操作語言:
CMD | Description |
---|---|
INSERT | 建立一條記錄。 |
UPDATE | 修改記錄。 |
DELETE | 刪除記錄。 |
(DQL)資料查詢語言:
CMD | Description |
---|---|
SELECT | 從一個或多個表中檢索某些記錄。 |
Sqlite點命令
先看一張Windows下的截圖:
這是在Windows的cmd下執行sqlite3命令(如何安裝和配置煩請自行google | baidu),然後依據提示執行.help的列印(只截圖一部分)。
可以發現sqlite的help列出來了所有sqlite支援的點命令,也可以發現,點命令不需要已”;”結尾。
我們對上面的.help命令進行翻譯大致如下:
CMD | Description |
---|---|
.backup ?DB? FILE |
備份DB資料庫(預設是”main”)到FILE檔案。 |
.bail ON/OFF |
發生錯誤後停止。預設為OFF。 |
.databases |
列出附加資料庫的名稱和檔案。 |
.dump ?TABLE? |
以SQL文字格式轉儲資料庫。如果指定了TABLE表,則只轉儲匹配LIKE模式的TABLE表。 |
.echo ON/OFF |
開啟或關閉echo命令。 |
.exit |
退出SQLite提示符。 |
.explain ON/OFF |
開啟或關閉適合於EXPLAIN的輸出模式。如果沒有帶引數,則為EXPLAIN on,及開啟EXPLAIN。 |
.header(s) ON/OFF |
開啟或關閉頭部顯示。 |
.help |
顯示訊息。 |
.import FILE TABLE |
匯入來自FILE檔案的資料到TABLE表中。 |
.indices ?TABLE? |
顯示所有索引的名稱。如果指定了TABLE表,則只顯示匹配LIKE模式的TABLE表的索引。 |
.load FILE ?ENTRY? |
載入一個擴充套件庫。 |
.log FILE/off |
開啟或關閉日誌。FILE檔案可以是stderr(標準錯誤)/stdout(標準輸出)。 |
.mode MODE |
設定輸出模式,MODE可以是下列之一:csv 逗號分隔的值;column 左對齊的列;html HTML的<table> 程式碼;insert TABLE表的SQL插入(insert)語句;line 每行一個值;list 由 .separator字串分隔的值;tabs 由Tab分隔的值;tcl TCL列表元素。 |
.nullvalue STRING |
在NULL值的地方輸出STRING字串。 |
.output FILENAME |
傳送輸出到FILENAME檔案。 |
.output stdout |
傳送輸出到螢幕。 |
.print STRING... |
逐字地輸出STRING字串。 |
.prompt MAIN CONTINUE |
替換標準提示符。 |
.quit |
退出SQLite提示符。 |
.read FILENAME |
執行FILENAME檔案中的SQL。 |
.schema ?TABLE? |
顯示CREATE語句。如果指定了TABLE表,則只顯示匹配LIKE模式的TABLE表。 |
.separator STRING |
改變輸出模式和.import所使用的分隔符。 |
.show |
顯示各種設定的當前值。 |
.stats ON/OFF |
開啟或關閉統計。 |
.tables ?PATTERN? |
列出匹配LIKE模式的表的名稱。 |
.timeout MS |
嘗試開啟鎖定的表MS微秒。 |
.width NUM NUM |
為”column”模式設定列寬度。 |
.timer ON/OFF |
開啟或關閉CPU定時器測量。 |
Sqlite資料庫的sqlite_master表
主表中儲存資料庫表的關鍵資訊,並把它命名為sqlite_master。如要查看錶概要,可如下操作:
1 | sqlite>.schema sqlite_master |
Sqlite語法規則
SQLite是遵循一套獨特的稱為語法的規則和準則。
SQLite是不區分大小寫的,但也有一些命令是大小寫敏感的,比如GLOB和glob在SQLite的語句中有不同的含義。
SQLite 註釋是附加的註釋,可以在 SQLite 程式碼中添加註釋以增加其可讀性,他們可以出現在任何空白處,包括在表示式內和其他 SQL 語句的中間,但它們不能巢狀。
SQL註釋以兩個連續的”-“字元開始,並擴充套件至下一個換行符或直到輸入結束,以先到者為準。也可以以”/*"
開始,並擴充套件至下一個 “*/
” 字元對或直到輸入結束,以先到者為準。SQLite的註釋可以跨越多行。
SQLite語句以任何關鍵字開始,以”;”結束。
Sqlite資料型別
SQLite資料型別是一個用來指定任何物件的資料型別的屬性。SQLite 中的每一列,每個變數和表示式都有相關的資料型別。您可以在建立表的同時使用這些資料型別。SQLite使用一個更普遍的動態型別系統。在SQLite中,值的資料型別與值本身是相關的,而不是與它的容器相關。
儲存類
SQLite有5個原始的資料型別,被稱為儲存類。儲存類這個詞表明瞭一個值在磁碟上儲存的格式,其實就是型別或資料型別的同義詞。如下即是儲存類:
儲存類 | Description |
---|---|
NULL | 值是一個NULL值。 |
INTEGER | 值是一個帶符號的整數,根據值的大小儲存在1、2、3、4、6 或8位元組中。 |
REAL | 值是一個浮點值,儲存為8位元組的IEEE浮點數字。 |
TEXT | 值是一個文字字串,使用資料庫編碼(UTF-8、UTF-16BE或UTF-16LE)儲存。 |
BLOB | 值是一個blob資料,完全根據它的輸入儲存。 |
SQLite通過值的表示法來判斷其型別,下面就是SQLite的推理方法:
- SQL語句中用單引號或雙引號括起來的文字被指派為TEXT。
- 如果文字是未用引號括起來的資料,並且沒有小數點和指數,被指派為INTEGER。
- 如果文字是未用引號括起來的資料,並且帶有小數點或指數,被指派為REAL。
- 用NULL說明的值被指派為NULL儲存類。
- 如果一個值的格式為X’ABCD’,其中ABCD為16進位制數字,則該值被指派為BLOB。X字首大小寫皆可。
如下就是驗證結果:
SQLite單獨的一個欄位可能包含不同儲存類的值。
如下就是驗證結果:
喜歡鑽牛角尖的這時候指定開始BB了,temp這一列資料型別不同,咋樣比較大小?咋樣排序等等?
經過查閱資料發現,具有不同儲存類的值可以儲存在同一個欄位中。可以被排序,因為這些值可以相互比較。有完善定義的規則來做這件事。不同儲存類的值可以通過它們各自類的“類值”進行排序,定義如下:
- NULL儲存類具有最低的類值。一個具有NULL儲存類的值比所有其它值都小(包括其它具有NULL儲存類的值)。在NULL值之間,沒有特別的可排序值。
- INTEGER或REAL儲存類值高於NULL,它們的類值相等。INTEGER值和REAL值通過其數值進行比較。
- TEXT儲存類的值比INTEGER和REAL高。數值永遠比字串的值低。當兩個TEXT值進行比較時,其值大小由“排序法”決定。
- BLOB儲存類具有最高的類值。具有BLOB類的值大於其它所有類的值。BLOB值之間在比較時使用C函式memcmp()。
所以,當SQLite對一個欄位進行排序時,首先按儲存類排序,然後再進行類內的排序 (NULL類內部各值不必排序) 。
弱型別(manifest typing)
首先有如下SQL語句:
MySQL12 | CREATETABLEtable_yanbo(xinteger,ytext,zreal);INSERTINTOtable_yanboVALUES('1','1','1'); |
這裡的x、y和z這3個欄位中儲存的是INTEGER, TEXT和REAL型別。
再看下面例子:
12 | CREATE TABLE table_yanbo(x,y,z);INSERT INTO table_yanbo VALUES('1', '1', '1'); |
這裡的x、y和z這3個欄位中儲存的是TEXT、TEXT和TEXT型別。
再看下面例子:
MySQL12 | CREATETABLEtable_yanbo(x,y,z);INSERTINTOtable_yanboVALUES(1,1.0,x'10'); |
這裡的x、y和z這3個欄位中儲存的是INTEGER、REAL和BLOB型別。
通過上面幾種寫法你會發現,可以為SQLite的欄位定義型別,但這不是必須的,你可以儘管違反型別定義。這是因為在任何情況下,SQLite都可以接受一個值並推斷它的型別。
總之,SQLite的弱型別可表示為:
- 欄位可以有型別。
- 型別可以通過值來推斷。
型別親和性介紹這兩個規定如何相互關聯。所謂型別親和性就是在強型別(strict typing)和動態型別(dynamic typing)之間的平衡藝術。
型別親和性(Type Affinity)
在SQLite中,欄位沒有型別或域。當給一個欄位聲明瞭型別,該欄位實際上僅僅具有了該型別的親和性。宣告型別和型別親和性是兩回事。型別親和性預定SQLite用什麼儲存類在欄位中儲存值。在儲存一個給定的值時到底SQLite會在該欄位中用什麼儲存類決定於值的儲存類和欄位親和性的結合。
任何列可以儲存任何型別的資料,但列的首選儲存類是它的affinity。在SQLite3資料庫中,每個表的列分配為以下型別的affinity之一:
Affinity | Description |
---|---|
TEXT | 該列使用儲存類NULL、TEXT或BLOB儲存所有資料。 |
NUMERIC | 該列可以包含使用所有五個儲存類的值。 |
INTEGER | 與帶有NUMERIC affinity的列相同,在CAST表示式中帶有異常。 |
REAL | 與帶有NUMERIC affinity的列相似,不同的是,它會強制把整數值轉換為浮點表示。 |
NONE | 帶有affinity NONE的列,不會優先使用哪個儲存類,也不會嘗試把資料從一個儲存類強制轉換為另一個儲存類。 |
下表列出了當建立SQLite3表時可使用的各種資料型別名稱,同時也顯示了相應的應用Affinity:
資料型別 | Affinity |
---|---|
INT、NTEGER、TINYINT、SMALLINT、MEDIUMINT、BIGINT、UNSIGNED BIG INT、INT2、INT8 | INTEGER |
CHARACTER(20)、VARCHAR(255)、VARYING CHARACTER(255)、NCHAR(55)、NATIVE CHARACTER(70)、NVARCHAR(100)、TEXT、CLOB | TEXT |
BLOB、no datatype specified | NONE |
REAL、DOUBLE、DOUBLE PRECISION、FLOAT | REAL |
NUMERIC、DECIMAL(10,5)、BOOLEAN、DATE、DATETIME | NUMERIC |
Boolean資料型別
SQLite沒有單獨的Boolean儲存類,布林值被儲存為整數 0(false)和 1(true)。
Date與Time資料型別
SQLite沒有一個單獨的用於儲存日期和/或時間的儲存類,但SQLite 能夠把日期和時間儲存為TEXT、REAL或 INTEGER值。您可以以任何上述格式來儲存日期和時間,並且可以使用內建的日期和時間函式來自由轉換不同格式。
儲存類 | 日期格式 |
---|---|
TEXT | 格式為”YYYY-MM-DD HH:MM:SS.SSS”的日期。 |
REAL | 從公元前4714年11月24日格林尼治時間的正午開始算起的天數。 |
INTEGER | 從1970-01-01 00:00:00 UTC算起的秒數。 |
欄位型別和親和性
首先,每個欄位都具有一種親和性。共有五種親和性:NUMERIC、INTEGER、REAL、TEXT和NONE。一個欄位的親和性由它預宣告的型別決定。所以,當你為欄位聲明瞭型別,從根本上說是為欄位指定了親和性。SQLite按下面的規則為欄位指派親和性:
- 預設的,一個欄位預設的親和性是NUMERIC。如果一個欄位不是INTEGER、TEXT、REAL或NONE的,那它自動地被指派為NUMERIC親和性。
- 如果為欄位宣告的型別中包含了’INT’(無論大小寫),該欄位被指派為INTEGER親和性。
- 如果為欄位宣告的型別中包含了’CHAR’、’CLOB’或’TEXT’(無論大小寫),該欄位被指派為TEXT親和性。如’VARCHAR’包含了’CHAR’,所以被指派為TEXT親和性。
- 如果為欄位宣告的型別中包含了’BLOB’(無論大小寫),或者沒有為該欄位宣告型別,該欄位被指派為NONE親和性。
注意:如果沒有為欄位宣告型別,該欄位的親和性為NONE,在這種情況下,所有的值都將以它們本身的(或從它們的表示法中推斷的)儲存類儲存。如果你暫時還不確定要往一個欄位裡放什麼內容,或準備將來修改,用NONE親和性是一個好的選擇。但SQLite預設的親和性是NUMERIC。例如,如果為一定欄位聲明瞭型別JUJYFRUIT,該欄位的親和性不是NONE,因為SQLite不認識這種型別,會給它指派預設的NUMERIC親和性。所以,與其用一個不認識的型別最終得到NUMERIC親和性,還不如不為它指定型別,從而使它得到NONE親和性。
親和性和儲存
親和性對值如何儲存到欄位有影響,規則如下:
- 一個NUMERIC欄位可能包括所有5種儲存類。一個NUMERIC欄位具有數字儲存類的偏好(INTEGER和REAL)。當一個TEXT值被插入到一個NUMERIC欄位,將會試圖將其轉化為INTEGER儲存類;如果轉化失敗,將會試圖將其轉化為REAL儲存類;如果還是失敗,將會用TEXT儲存類來儲存。
- 一個INTEGER欄位的處理很像NUMERIC欄位。一個INTEGER欄位會將REAL值按REAL儲存類儲存。也就是說,如果這個REAL值沒有小數部分,就會被轉化為INTEGER儲存類。INTEGER欄位將會試著將TEXT值按REAL儲存;如果轉化失敗,將會試圖將其轉化為INTEGER儲存類;如果還是失敗,將會用TEXT儲存類來儲存。
- 一個TEXT欄位將會把所有的INTEGER或REAL值轉化為TEXT。
- 一個NONE欄位不試圖做任何型別轉化。所有值按它們本身的儲存類儲存。
- 沒有欄位試圖向NULL或BLOB值轉化——如無論用什麼親和性。NULL和BLOB值永遠都按本來的方式儲存在所有欄位。
這些規則初看起來比較複雜,但總的設計目標很簡單,如果你需要,SQLite會盡量模仿其它的關係型資料庫。也就是說,如果你將SQLite看成是一個傳統資料庫,型別親和性將會按你的期望來儲存值。如果你聲明瞭一個INTEGER欄位,並向裡面放一個整數,就會按整數來儲存。如果你聲明瞭一個具有TEXT, CHAR或VARCHAR型別的欄位並向裡放一個整數,整數將會轉化為TEXT。可是,如果你不遵守這些規定,SQLite也會找到辦法來儲存你的值。
如下例子展示了親和性是如何工作的:
儲存類和型別轉換
關於儲存類,需要關注的另一件事是儲存類有時會影響到值如何進行比較。特別是SQLite有時在進行比較之前,會將值在數字儲存類(INTEGER和REAL)和TEXT之間進行轉換。為進行二進位制的比較,遵循如下規則:
- 當一個欄位值與一個表示式的結果進行比較,欄位的親和性會在比較之前應用於表示式的結果。
- 當兩個欄位值進行比較,如果一個欄位擁有INTEGER或NUMERIC親和性而另一個沒有,NUMERIC親和性會應用於非NUMERIC欄位的TEXT值。
- 當兩個表示式進行比較,SQLite不做任何轉換。如果兩個表示式有相似的儲存類,則直接按它們的值進行比較;否則按類值進行比較。
總結
這裡主要介紹了Sqlite的一些基本概念和資料型別的特性。關於Sqlite其他內容接下來文章繼續介紹。繼續閱讀下一篇《Sqlite全面學習(二)》。