1. 程式人生 > >Sqlite全面學習(一)

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&gt;.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語句:

MySQL
12 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(&#039;1&#039;, &#039;1&#039;, &#039;1&#039;);

這裡的x、y和z這3個欄位中儲存的是TEXT、TEXT和TEXT型別。

再看下面例子:

MySQL
12 CREATETABLEtable_yanbo(x,y,z);INSERTINTOtable_yanboVALUES(1,1.0,x'10');

這裡的x、y和z這3個欄位中儲存的是INTEGER、REAL和BLOB型別。

通過上面幾種寫法你會發現,可以為SQLite的欄位定義型別,但這不是必須的,你可以儘管違反型別定義。這是因為在任何情況下,SQLite都可以接受一個值並推斷它的型別。

總之,SQLite的弱型別可表示為:

  1. 欄位可以有型別。
  2. 型別可以通過值來推斷。

型別親和性介紹這兩個規定如何相互關聯。所謂型別親和性就是在強型別(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全面學習(二)》。