SQLite 第三版總覽
SQLite 第三版主要主要介紹關(guān)于類庫(kù)的一些變化, 包括:
- 介紹了一個(gè)關(guān)于數(shù)據(jù)庫(kù)文件的更緊湊的格式.
- 若類型和 BLOB 支持.
- 支持 UTF-8 and UTF-16 文本.
- 用戶定義的文件排列順序.
- 64字節(jié)的行編號(hào).
- 針對(duì)并發(fā)性的一些改良.
這篇文檔簡(jiǎn)易的介紹了SQlite3.0版針對(duì)于2.8版的一些改進(jìn),適用于對(duì)SQlite2.8版比較了解的用戶。
命名上的變化
在可預(yù)見(jiàn)的未來(lái),錯(cuò)誤修正這項(xiàng)功能將繼續(xù)支持SQLite 2.8版。為了保證這兩個(gè)版本可以共存,在3.0版本中,一些主要文件的名稱和API的名稱中都加了個(gè)”3“。例如, c程序內(nèi)含文件的名稱已經(jīng)從"sqlite.h"改為"sqlite3.h".還有,用來(lái)和數(shù)據(jù)庫(kù)一起操作的數(shù)據(jù)命令解釋程序也從"sqlite.exe" 改為 "sqlite3.exe"。有了這些命名上的區(qū)別,SQLite 2.8版和SQLite 3.0版就可以同時(shí)安裝在同一個(gè)系統(tǒng)下了。另外,名稱上的區(qū)別也使同一個(gè)C程序可以同時(shí)和2.8,3.0兩個(gè)版本同時(shí)相連并使用同一個(gè)類庫(kù)。
新的文件格式
SQlite的數(shù)據(jù)庫(kù)文件格式已被完全更新, 2.1版的格式和3.0版的格式是互不兼容的。比如,2.8版的SQLite 是無(wú)法讀取3.0版的SQlite數(shù)據(jù)庫(kù)文件的,同樣,3.0版的SQLite也是無(wú)法讀取2.8版的 SQlite數(shù)據(jù)庫(kù)文件的。
如想把SQLite 2.8版的數(shù)據(jù)庫(kù)轉(zhuǎn)換成3.0版的數(shù)據(jù)庫(kù)的話,你可以用一些現(xiàn)成的命令行操作,比如輸入下面的命令:
sqlite OLD.DB .dump | sqlite3 NEW.DB
新的數(shù)據(jù)庫(kù)文件格式使用B+樹(shù)型數(shù)據(jù)表格。在B+樹(shù)中,所有的數(shù)據(jù)都被存儲(chǔ)在(數(shù)據(jù)結(jié)構(gòu)中)樹(shù)結(jié)構(gòu)端結(jié)點(diǎn),而不是既在(數(shù)據(jù)結(jié)構(gòu)中)樹(shù)結(jié)構(gòu)端結(jié)點(diǎn)又在樹(shù)的分支節(jié)點(diǎn)。B+樹(shù)型數(shù)據(jù)表格具有很好的測(cè)量性,并且可以存儲(chǔ)比較大的數(shù)據(jù)組。此外,傳統(tǒng)的B-樹(shù)也仍被應(yīng)用在SQlite3.0的許多目錄中。
新的文件格式可以存儲(chǔ)的可變頁(yè)的長(zhǎng)度在512和32768字節(jié)之間。每頁(yè)的文件長(zhǎng)度都可以在頁(yè)眉顯示出來(lái),所以從理論上來(lái)說(shuō),同一個(gè)類庫(kù)可以讀取不同長(zhǎng)度的數(shù)據(jù)庫(kù),但實(shí)際上這一點(diǎn)還沒(méi)有完全實(shí)現(xiàn)。
新的文件格式在磁盤映像中省略了沒(méi)有被應(yīng)用的區(qū)域。例如,目錄僅僅顯示B-樹(shù)所存儲(chǔ)的主要部分而不是顯示所有的數(shù)據(jù)。也就是說(shuō),記錄數(shù)據(jù)長(zhǎng)度的區(qū)域被省略了。整數(shù)值,比如說(shuō)關(guān)鍵字的長(zhǎng)度和關(guān)鍵數(shù)據(jù)可以用變長(zhǎng)量來(lái)編譯,這樣一來(lái),最常見(jiàn)的數(shù)據(jù)就可以只用一兩個(gè)字節(jié)來(lái)顯示了,還有,如果需要的話,最高64字節(jié)的數(shù)據(jù)信息也是可以編譯的。 在3.0版中,整數(shù)和浮動(dòng)的點(diǎn)數(shù)據(jù)是用二進(jìn)制來(lái)記錄的,但在2.0版中,它們則是被轉(zhuǎn)換成ASCII碼的。所以,同一個(gè)數(shù)據(jù)庫(kù)文件,如果是記錄在SQlite3.0中,就可以比記錄在SQlite2.8中少占用25%至30%的磁盤空間。
關(guān)于 SQLite3.0版所采用的B-樹(shù)的文件格式具體細(xì)節(jié),你可以點(diǎn)擊 btree.c 看標(biāo)題注釋。
弱類型和BLOB技術(shù)支持
SQLite2.8在數(shù)據(jù)庫(kù)內(nèi)部可以用不同的文件格式處理文件,但是,如果想把信息寫(xiě)到硬盤或是通過(guò)API和其它數(shù)據(jù)相連,所有文件格式都必須被轉(zhuǎn)換成ASCII文本格式。SQLite 3.0則不同,它可以把數(shù)據(jù)可內(nèi)部的主要數(shù)據(jù),也就是上文所提到的用變長(zhǎng)量所表示的數(shù)據(jù)顯示給用戶,并在適當(dāng)?shù)臅r(shí)候用二進(jìn)制的形式在磁盤中顯示。為了支持BLOB,非ASCII格式的數(shù)據(jù)也可以在磁盤中顯示。
SQLite 2.8版有一個(gè)特點(diǎn),就是任何類型的數(shù)據(jù)都可以存儲(chǔ)在任意的數(shù)據(jù)列中,不受數(shù)據(jù)列所要求存儲(chǔ)的文件類型的限制。這個(gè)特性被保留在3.0版中并有所改進(jìn)。雖然數(shù)據(jù)文件的格式?jīng)Q定了文件的類型,每列所存儲(chǔ)的文件都要有規(guī)定的屬性,但在3.0中每個(gè)列都是可以存儲(chǔ)不同類型的數(shù)據(jù)的。當(dāng)數(shù)據(jù)被存入一個(gè)數(shù)據(jù)列的時(shí)候,這個(gè)列將盡全力把存入的數(shù)據(jù)的文件格式轉(zhuǎn)換成該列所要求的文件格式。所有的SQL數(shù)據(jù)庫(kù)引擎都是這樣的。所不同的是,SQLite 3.0 將存儲(chǔ)數(shù)據(jù)即使轉(zhuǎn)換該數(shù)據(jù)的文件類型是不可能的。
例如,一個(gè)數(shù)據(jù)列要求所存儲(chǔ)的文件的類型是 "INTEGER",你輸入一個(gè)字符串,這個(gè)列將自動(dòng)檢查所輸入的字符串是否是數(shù)字,如果它確實(shí)看起來(lái)像是數(shù)字,字符串將被轉(zhuǎn)換成數(shù)字,然后,如果這個(gè)數(shù)字沒(méi)有分?jǐn)?shù)部分的話,它將被轉(zhuǎn)換成整數(shù)存儲(chǔ)起來(lái)。但是如果這個(gè)字符串不是一個(gè)規(guī)則的數(shù)字的話,它將仍被保存為一個(gè)字符串。如果一個(gè)列要求所存儲(chǔ)的文件的類型是"TEXT"的話,在存儲(chǔ)數(shù)據(jù)之前,列將嘗試把數(shù)字轉(zhuǎn)換成 ASCII-Text來(lái)表示數(shù)據(jù)。但是,BLOBS在文本列仍然被保存成BLOBS,因?yàn)樵谕ǔG闆r下你是不可能把BLOB轉(zhuǎn)換成文本的。
在大部分的其他的SQL數(shù)據(jù)庫(kù)引擎中,數(shù)據(jù)類型是和他該數(shù)據(jù)所處列的類型緊密相連的,但在SQlite3.0中,一個(gè)數(shù)據(jù)的類型只和自身有關(guān),和所屬列所要求的數(shù)據(jù)類型沒(méi)有任何關(guān)聯(lián)。 Paul Graham 在他的 ANSI Common Lisp一書(shū)中稱這個(gè)特性"manifest typing"為"弱類型". 其他的作者對(duì)"manifest typing"有不同的定義,我們不要混淆,不管它的名稱是什么,我們知道它是3.0 的一個(gè)特性就好。
關(guān)于SQLite3.0版的數(shù)據(jù)類型的更多內(nèi)容,點(diǎn)擊separately.
支持UTF-8和UTF-16
在SQLite 3.0中,API中的程序可以識(shí)別UTF-8和UTF-16文本,并不改變主機(jī)中原來(lái)字節(jié)的順序。每個(gè)數(shù)據(jù)庫(kù)文件都可以用UTF-8, UTF-16BE (big-endian)和 UTF-16LE (little-endian)兩種方式處理文本。在磁盤文件的內(nèi)部,到處可見(jiàn)到同樣的文本顯示。如果數(shù)據(jù)庫(kù)文件中所記載的文本顯示(在文件標(biāo)題中)和接口程序所要求的文本顯示不相符合的話,文本將被轉(zhuǎn)換成當(dāng)前所要求的文本格式。經(jīng)常轉(zhuǎn)換文本格式對(duì)于程序來(lái)說(shuō)是非常麻煩的,所以建議程序員在一個(gè)應(yīng)用程序中自始至終使用一種文本格式。
當(dāng)前,在執(zhí)行SQLite的時(shí)候,SQL的語(yǔ)法只能識(shí)別UTF-8文本,所以如果是UTF-16文本的話將被轉(zhuǎn)換成UTF-8文本。當(dāng)然這只是程序執(zhí)行的問(wèn)題,在不遠(yuǎn)的將來(lái),更新版本的SQLite將完全有實(shí)力識(shí)別用SQL所編譯的UTF-16文本。
當(dāng)開(kāi)發(fā)用戶所定義的SQL函數(shù)和分類排序功能的時(shí)候,不管是UTF-8,UTF-16be或是 UTF-16le 文本格式,每個(gè)函數(shù)和分類排序都能清晰的識(shí)別文件。程序所執(zhí)行的每一步都被完整無(wú)誤的記錄下來(lái)以便編譯。當(dāng)SQL函數(shù)或分類排序要求相應(yīng)的格式,但當(dāng)前版本的文件編譯又無(wú)能為力的時(shí)候,文本將自動(dòng)被轉(zhuǎn)換。像以前一樣,這種轉(zhuǎn)換需要一定的時(shí)間,所以建議程序員挑選一種編碼并自始至終使用以避免不必要的文本格式轉(zhuǎn)換。
不只是對(duì)于一個(gè)完整的文本,即使是某個(gè)文本中的格式不規(guī)則的字符串和格式不規(guī)則的UTF-8和UTF-16文本行,SQLite也要竭盡全力把他們編譯成規(guī)則的文件格式。所以如果你想存儲(chǔ)IS08859數(shù)據(jù)的話,你可以使用UTF-8接口程序。只要不使用UTF-16分類排序或SQL函數(shù),文本的字節(jié)順序?qū)⒉粫?huì)被變更。
用戶定義的分類排序
所謂的分類排序是指文本的排列順序。當(dāng)SQLite 3.0分類的時(shí)候(比如使用比較操作符"<" or ">="),它是按照數(shù)據(jù)類型分類的。
- 首先把空行分類
- 按數(shù)字的順序把數(shù)值分類
- 再把文本分類
- 最后把BLOBs分類
當(dāng)比較兩個(gè)文本行的時(shí)候使用分類排序。分類排序不改變空行,數(shù)字和BLOBS的順序,它只改變文本的順序。
分類排序功能是作為一個(gè)函數(shù)來(lái)執(zhí)行的,它使用兩個(gè)字符串來(lái)表示,如果第一個(gè)字符串小于第二個(gè)字符串,則顯示為負(fù)數(shù),如等于則顯示為零,如大于則顯示為正數(shù)。 SQLite 3.0版設(shè)置了一個(gè)名叫BINARY的獨(dú)立的內(nèi)置分類排序功能,它是依靠標(biāo)準(zhǔn)C類庫(kù)中的memcmp()程序來(lái)實(shí)現(xiàn)的。 BINARY分類排序功能很好的支持英文文檔。對(duì)于其他語(yǔ)言或者在其他場(chǎng)合,程序會(huì)根據(jù)需要來(lái)選擇合適的分類排序功能。
使用哪種分類排序是由SQL中的COLLATE語(yǔ)句來(lái)決定的。一個(gè)COLLATE語(yǔ)句可分辨一種表格,它可以定義并默認(rèn)表格中的每列該使用哪種分類排序,目錄的每個(gè)區(qū)段該使用哪種分類排序,或SELECTED語(yǔ)句中ORDER BY 字句該使用哪種分類排序。按照計(jì)劃,SQLite還將使用標(biāo)準(zhǔn)的CAST()句法來(lái)具體定義每個(gè)分類排序。
64字節(jié)的行編號(hào)
表格中的每一行都有行標(biāo)識(shí)符。如果表格中的某一列被定義為整數(shù)初級(jí)鍵控,那么那一列就成為其所屬行的別名。但不管有沒(méi)有定義這樣一個(gè)列,每個(gè)行都是有行編號(hào)的。
在SQLite 3.0版中,行編號(hào)是64字節(jié)的帶符號(hào)整數(shù)。而在SQLite2.8中,行編號(hào)是32字節(jié)的。
為了占有最小的存儲(chǔ)空間,64字節(jié)的行編號(hào)被存儲(chǔ)為變長(zhǎng)量。行編號(hào)在0和127之間的都只占有一個(gè)字節(jié)的空間。行編號(hào)在128和16383之間的只占用2個(gè)字節(jié)的空間。 行編號(hào)在16383和2097152之間的占有三個(gè)字節(jié)的空間。依此類推。也可以使用負(fù)行編號(hào),擔(dān)負(fù)行編號(hào)通常要占用9個(gè)字節(jié)的空間, 所以建議不要使用。SQLite所自動(dòng)生成的行編號(hào)通常不是負(fù)行編號(hào)。
改良的并發(fā)性
SQLite 2.8允許多個(gè)進(jìn)程同時(shí)讀取或一個(gè)進(jìn)程讀取,但不允許讀取和寫(xiě)入同時(shí)進(jìn)行。SQLite 3.0則允許一個(gè)進(jìn)程寫(xiě)入和其它多個(gè)進(jìn)程同時(shí)讀取。為了確認(rèn)所更新的數(shù)據(jù),輸入者必須為數(shù)據(jù)庫(kù)中的簡(jiǎn)短區(qū)間設(shè)置一個(gè)額外的鎖,但這個(gè)鎖不再像以前那樣必須貫穿在整個(gè)輸入過(guò)程中。可以點(diǎn)擊找到關(guān)于SQLite3.0 版中的鎖的具體信息。
SQLite中也有一個(gè)在格式上有局限性的表格極的鎖. 如果每個(gè)表格都存儲(chǔ)了不同類型的文件,這些文件可以被連接到主數(shù)據(jù)庫(kù)(使用ATTACH命令),這個(gè)被整合在一起的數(shù)據(jù)庫(kù)依然可以作為一個(gè)整體來(lái)運(yùn)行。但各個(gè)文件將按照需要生成各自的鎖。所以如果你把“數(shù)據(jù)庫(kù)”重新定義成兩個(gè)或更多數(shù)據(jù)庫(kù)文件,那么在同一個(gè)數(shù)據(jù)庫(kù)中同時(shí)對(duì)兩個(gè)進(jìn)程寫(xiě)入則是完全可能的。為了更好的支持這項(xiàng)功能,同時(shí)處理兩個(gè)或更多的ATTACHed型數(shù)據(jù)庫(kù)是最基本的了。
致謝
SQLite3.0版的成功發(fā)行得利于AOL開(kāi)發(fā)者的大力支持和開(kāi)源軟件的幫助。
SQLite第三版中的數(shù)據(jù)類型
1.存儲(chǔ)類別
第二版把所有列的值都存儲(chǔ)成ASCII文本格式。第三版則可以把數(shù)據(jù)存儲(chǔ)成整數(shù)和實(shí)數(shù),還可以存儲(chǔ)BLOB數(shù)據(jù).
Each value stored in an SQLite數(shù)據(jù)庫(kù)中存儲(chǔ)的每個(gè)值都有一個(gè)屬性,都屬于下面所列類中的一種,(被數(shù)據(jù)庫(kù)引擎所控制)
· 空.這個(gè)值為空值
· 整數(shù).值被標(biāo)識(shí)為整數(shù),依據(jù)值的大小可以依次被存儲(chǔ)為1,2,3,4,5,6,7,8.
· 實(shí)數(shù). 所有值都是浮動(dòng)的數(shù)值,被存儲(chǔ)為8字節(jié)的IEEE浮動(dòng)標(biāo)記序號(hào).
· 文本. 值為文本字符串,使用數(shù)據(jù)庫(kù)編碼存儲(chǔ)(TUTF-8, UTF-16BE or UTF-16-LE).
· BLOB. 值是BLOB數(shù)據(jù),如何輸入就如何存儲(chǔ),不改變格式.
像SQLite2.0版一樣,在3.0版中,除了INTEGER PRIMARY KEY,數(shù)據(jù)庫(kù)中的任何列都可以存儲(chǔ)任何類型的數(shù)據(jù).這一規(guī)則也有例外,在下面的"嚴(yán)格相似模式"中將描述.
輸入SQLite的所有值,不管它是嵌入 SQL語(yǔ)句中的文字還是提前編譯好的綁定在SQL語(yǔ)句中的值,在SQL語(yǔ)句執(zhí)行前都被存儲(chǔ)為一個(gè)類.在下面所描述的情況下,數(shù)據(jù)庫(kù)引擎將在執(zhí)行時(shí)檢查并把值在數(shù)字存儲(chǔ)類(整數(shù)和實(shí)數(shù))和文本類間轉(zhuǎn)換.
存儲(chǔ)的類別最初被分類為如下:
· 具體的值比如SQL語(yǔ)句部分的帶雙引號(hào)或單引號(hào)的文字被定義為文本,如果文字沒(méi)帶引號(hào)并沒(méi)有小數(shù)點(diǎn)或指數(shù)則被定義為整數(shù),如果文字沒(méi)帶引號(hào)但有小數(shù)點(diǎn)或指數(shù)則被定義為實(shí)數(shù),如果值是空則被定義為空值.BLOB數(shù)據(jù)使用符號(hào)X'ABCD'來(lái)標(biāo)識(shí).
· Values supplied using the 被輸入的值使用sqlite3_bind_* APIs的被分類一個(gè)存儲(chǔ)等級(jí),這等級(jí)是和原來(lái)的類基本相一致的. (比如sqlite3_bind_blob()綁定一個(gè)BLOB的值).
值的分類是SQL分等級(jí)操作的結(jié)果,決定于最遠(yuǎn)的操作表達(dá)式.用戶定義的功能也許會(huì)把值返回任意的類.在編譯的時(shí)候來(lái)確定表達(dá)式的存儲(chǔ)類基本是不可能的.
2. 列之間的親和性
在SQLite3.0版中,值被定義為什么類型只和值自身有關(guān),和列沒(méi)有關(guān)系,和變量也沒(méi)有關(guān)系. (這有時(shí)被稱作 弱類型.)所有其它的我們所使用的數(shù)據(jù)庫(kù)引擎都受靜態(tài)類型系統(tǒng)的限制,其中的所有值的類是由其所屬列的屬性決定的,而和值無(wú)關(guān).
為了最大限度的增加SQLite數(shù)據(jù)庫(kù)和其他數(shù)據(jù)庫(kù)的兼容性,SQLite支持列的"類型親和性". 列的親和性是為該列所存儲(chǔ)的數(shù)據(jù)建議一個(gè)類型.我們要注意是建議而不是強(qiáng)迫.在理論上來(lái)講,任何列依然是可以存儲(chǔ)任何類型的數(shù)據(jù)的. 只是針對(duì)某些列,如果給建議類型的話,數(shù)據(jù)庫(kù)將按所建議的類型存儲(chǔ).這個(gè)被優(yōu)先使用的數(shù)據(jù)類型則被稱為"親和類型".
在SQLite3.0版中,數(shù)據(jù)庫(kù)中的每一列都被定義為以下親和類型中的一種:
- 文本
- 數(shù)字的
- 整數(shù)
- 無(wú)
一個(gè)具有類型親和性的列按照無(wú)類型,文本,或BLOB存儲(chǔ)所有的數(shù)據(jù).如果數(shù)字?jǐn)?shù)據(jù)被插入一個(gè)具有文本類型親和性的列,在存儲(chǔ)之前數(shù)字將被轉(zhuǎn)換成文本.
一個(gè)具有數(shù)字類型親和性的列也許使用所有的五個(gè)存儲(chǔ)類型存儲(chǔ)值.當(dāng)文本數(shù)據(jù)被插入一個(gè)數(shù)字列時(shí),在存儲(chǔ)之前,數(shù)據(jù)庫(kù)將嘗試著把文本轉(zhuǎn)換成整數(shù)或?qū)崝?shù).如果能成功轉(zhuǎn)換的話,值將按證書(shū)活實(shí)數(shù)的類型被存儲(chǔ). 如果不能 成功轉(zhuǎn)換的話,值則只能按文本類型存儲(chǔ)了,而不會(huì)被轉(zhuǎn)換成無(wú)類型或BLOB類型來(lái)存儲(chǔ).
一個(gè)具有整數(shù)親和力的列在轉(zhuǎn)換方面和具有數(shù)字親和力的列是一樣的,但也有些區(qū)別 ,比如沒(méi)有浮動(dòng)量的實(shí)值(文本值轉(zhuǎn)換的值)被插入具有整數(shù)親和力的列時(shí),它將被轉(zhuǎn)換成整數(shù)并按整數(shù)類型存儲(chǔ).
一個(gè)具有無(wú)類型親和力的列不會(huì)優(yōu)先選擇使用哪個(gè)類型.在數(shù)據(jù)被輸入前它不會(huì)強(qiáng)迫數(shù)據(jù)轉(zhuǎn)換類型.
2.1 列的親和性的決定
一個(gè)列的親和類型是由該列所宣稱的類型決定的.遵守以下規(guī)則:
1. 如果數(shù)據(jù)類型包括字符串"INT"那么它被定義成具有整數(shù)親和性.
2. 如果列中的數(shù)據(jù)類型包括以下任何的字符串 "CHAR", "CLOB", or "TEXT" 那么這個(gè)列則具有文本親和性.要注意VARCHAR類型包括字符串"CHAR"因此也具有文本類型親和性.
3. 如果一個(gè)列的數(shù)據(jù)類型包括字符串"BLOB"或者如果數(shù)據(jù)類型被具體化了,那么這個(gè)列具有無(wú)類型親和性.
4. 否則就具有數(shù)字類型親和性.
如果表格使用If "CREATE TABLE
AS SELECT..."語(yǔ)句生成的,那么所有的列則都沒(méi)有具體的數(shù)據(jù)類型,則沒(méi)有類型親和性.
2.2 列的親和性的例子
CREATE TABLE t1(
t TEXT,
nu NUMERIC,
i INTEGER,
no BLOB
);
-- Storage classes for the following row:
-- TEXT, REAL, INTEGER, TEXT
INSERT INTO t1 VALUES('500.0', '500.0', '500.0', '500.0');
-- Storage classes for the following row:
-- TEXT, REAL, INTEGER, REAL
INSERT INTO t1 VALUES(500.0, 500.0, 500.0, 500.0);
3.比較表達(dá)式
像SQLite2.0版一樣,3.0版的一個(gè)特性是二進(jìn)制比較符'=', '<', '<=', '>=' and '!=',一個(gè)操作'IN'可以測(cè)試固定的成員資格, 三重的比較操作符'BETWEEN'.
比較的結(jié)果決定于被比較的兩個(gè)值的存儲(chǔ)類型。遵循以下規(guī)則:
· 一個(gè)具有空存儲(chǔ)類型的值被認(rèn)為小于任何值(包括另外一個(gè)具有空存儲(chǔ)類型的值)。
· 一個(gè)整數(shù)值或?qū)崝?shù)值小于任何文本值和BLOB值。當(dāng)一個(gè)整數(shù)或?qū)崝?shù)和另一個(gè)整數(shù)或?qū)崝?shù)相比較的時(shí)候,則按照實(shí)際數(shù)值來(lái)比較。
· 一個(gè)文本值小于BLOB值。當(dāng)兩個(gè)文本值相比較的時(shí)候,則用C語(yǔ)言類庫(kù)中的memcmp()函數(shù)來(lái)比較。然而,有時(shí)候也不是這樣的,比如在下面所描述的“用戶定義的整理順序”情況下。
· 當(dāng)兩個(gè)BLOB文本被比較的時(shí)候,結(jié)果決定于memcmp()函數(shù)。
在開(kāi)始比較前,SQLite嘗試著把值在數(shù)字存儲(chǔ)級(jí)(整數(shù)和實(shí)數(shù))和文本之間相互轉(zhuǎn)換。下面列舉了關(guān)于如何比較二進(jìn)制值的例子。在著重號(hào)below中使用的表達(dá)式可以表示SQL標(biāo)量表達(dá)式或是文本但不是一個(gè)列值。
· 當(dāng)一個(gè)列值被比擬為表達(dá)式結(jié)果的時(shí)候,在比較開(kāi)始前,列的親和性將被應(yīng)用在表達(dá)結(jié)果中。
· 當(dāng)兩個(gè)列值比較的時(shí)候,如果一個(gè)列有整數(shù)或數(shù)字親和性的時(shí)候,而另外一列卻沒(méi)有,那么數(shù)字親和性適用于從非數(shù)字列提取的任何具有文本存儲(chǔ)類型的值. P>
· 當(dāng)比較兩個(gè)表達(dá)式的結(jié)果時(shí),不發(fā)生任何轉(zhuǎn)換,直接比較結(jié)果.如果一個(gè)字符串和一個(gè)數(shù)字比較, 數(shù)字總是小于字符串.
在SQLite中, 表達(dá)式"a BETWEEN b AND c"等于表達(dá)式 "a >= b AND a <= c",在比較表達(dá)式時(shí),a可以是具有任何親和性.
表達(dá)式 "a IN (SELECT b ....)" 在比較時(shí)遵循上面所提到的三條規(guī)則,是二進(jìn)制比較.(例如, 在一個(gè)相似的樣式 "a = b"). 例如,如果'b'是一個(gè)列值, 'a' 是一個(gè)表達(dá)式,那么,在開(kāi)始比較前,'b'的親和性就被轉(zhuǎn)換為'a'的親和性了.
SQLite把表達(dá)式 "a IN (x, y, z)" 和 "a = z OR a = y OR a = z"視為相等.
3.1 比較例子
CREATE TABLE t1(
a TEXT,
b NUMERIC,
c BLOB
);
-- Storage classes for the following row:
-- TEXT, REAL, TEXT
INSERT INTO t1 VALUES('500', '500', '500');
-- 60 and 40 are converted to '60' and '40' and values are compared as TEXT.
SELECT a < 60, a < 40 FROM t1;
1|0
-- Comparisons are numeric. No conversions are required.
SELECT b < 60, b < 600 FROM t1;
0|1
-- Both 60 and 600 (storage class NUMERIC) are less than '500'
-- (storage class TEXT).
SELECT c < 60, c < 600 FROM t1;
0|0
4. 運(yùn)算符
所有的數(shù)學(xué)運(yùn)算符(所有的運(yùn)算符而不是連鎖作用標(biāo)記符"||")運(yùn)算對(duì)象首先具有數(shù)字親和性, 如果一個(gè)或是兩個(gè)都不能被轉(zhuǎn)換為數(shù)字那么操作的結(jié)果將是空值。
對(duì)于連接作用操作符,所有操作符將首先具有文本親和性。如果其中任何一個(gè)操作符不能被轉(zhuǎn)換為文本(因?yàn)樗强罩祷蚴?span lang="EN-US">BLOB)連接作用操作符將是空值。
5. 分類,排序,混合挑選
當(dāng)用子句ORDER挑選值時(shí),空值首先被挑選出來(lái), 然后是整數(shù)和實(shí)數(shù)按順序被挑選出來(lái), 然后是文本值按memcmp()順序被挑選出來(lái), 最后是BLOB值按memcmp()順序被挑選出來(lái).在挑選之前, 沒(méi)有存儲(chǔ)類型的值都被轉(zhuǎn)換了.
When grouping values with the 當(dāng)用GROUP BY子句給值分組時(shí),具有不同存儲(chǔ)類型的值被認(rèn)為是不同的, 但也有例外, 比如,一個(gè)整數(shù)值和一個(gè)實(shí)數(shù)值從數(shù)字角度來(lái)說(shuō)是相等的,那么它們則是相等的.用GROUP by 子句比較完后,值不具有任何親和性.
混合挑選操作符UNION, INTERSECT and EXCEPT 在值之間實(shí)行絕對(duì)的比較,同樣的親和性將被應(yīng)用于所有的值,這些值將被存儲(chǔ)在一個(gè)單獨(dú)的具有混合SELECT的結(jié)果組的列中. 被賦予的親和性是該列的親和性,這個(gè)親和性是由剩下的大部分的混合SELECTS返回的,這些混合SELECTS在那個(gè)位置上有列值(而不是其它類型的表達(dá)式). 如果一個(gè)給定的混合SELECT列沒(méi)有SELECTS的量, 那么在比較前,該列的值將不具有任何親和性.
6. 其它親和性模式
以上的部分所描述的都是數(shù)據(jù)庫(kù)引擎在正常親和性模式下所進(jìn)行的操作, SQLite將描述其它兩種親和性模式,如下:
· 嚴(yán)格親和性模式.在這種模式下,如果需要值之間相互轉(zhuǎn)換數(shù)據(jù)存儲(chǔ)類型的話,數(shù)據(jù)庫(kù)引擎將發(fā)送錯(cuò)誤報(bào)告,當(dāng)前語(yǔ)句也將會(huì)重新運(yùn)行.
· 無(wú)親和性模式.在這種模式下,值的數(shù)據(jù)存儲(chǔ)類型不發(fā)生轉(zhuǎn)換.具有不同存儲(chǔ)類型的值之間不能比較,但整數(shù)和實(shí)數(shù)之間可以比較.
7.用戶定義的校對(duì)順序
By default, when 當(dāng)SQLite比較兩個(gè)文本值的時(shí)候,通過(guò)系統(tǒng)設(shè)定,不管字符串的編碼是什么,用memcmp()來(lái)比較. SQLite第三版允許用戶提供任意的函數(shù)來(lái)代替memcmp(),也就是用戶定義的比較順序.
除了系統(tǒng)預(yù)設(shè)的BINARY比較順序,它是用memcmp()函數(shù)比較,SQLite還包含了兩個(gè)額外的內(nèi)置比較順序函數(shù), NOCASE和REVERSE:
- BINARY -使用memcmp()比較字符串?dāng)?shù)據(jù), 不考慮文本編碼.
- REVERSE -用倒序比較二進(jìn)制文本.
- NOCASE - 和二進(jìn)制一樣,但在比較之前,26位的大寫(xiě)字母盤要被折合成相應(yīng)的小寫(xiě)字母盤.
7.1 分配比較順序
每個(gè)表格中的每個(gè)列都有一個(gè)預(yù)設(shè)的比較類型.如果一個(gè)比較類型不是二進(jìn)制所要求的,比較的子句將被具體化為 列的定義 來(lái)定義該列.
當(dāng)用SQLite比較兩個(gè)文本值時(shí),比較順序?qū)凑找韵碌囊?guī)則來(lái)決定比較的結(jié)果.文檔的第三部分和第五部分描述在何種場(chǎng)合下發(fā)生這種比較.
對(duì)于二進(jìn)制比較符(=, <, >, <= and >=),如果每個(gè)操作數(shù)是一列的話,那么該列的默認(rèn)比較類型決定于所使用的比較順序. 如果兩個(gè)操作數(shù)都是列的話,那么左邊的操作數(shù)的比較類型決定了所要使用的比較順序.如果兩個(gè)操作數(shù)都不是一列,將使用二進(jìn)制來(lái)比較.
表達(dá)式"x BETWEEN y and z"和 "x >= y AND x <= z"是相同的. 表達(dá)式"x IN (SELECT y ...)" 和表達(dá)式 "x = y" 使用同樣的方法來(lái)操作,這是為了決定所要使用的比較順序.如果X是一列或者二進(jìn)制的,則"x IN (y, z ...)" 形式的表達(dá)式所使用的比較順序是X的默認(rèn)的比較類型.
ORDER BY clause that is part of a SELECT statement may be assigned a collation sequence to be used for the sort operation explicitly. In this case the explicit collation sequence is always used. Otherwise, if the expression sorted by an ORDER BY clause is a column, then the default collation type of the column is used to determine sort order. If the expression is not a column, then the BINARY collation sequence is used.
7.2 比較順序的例子
下面的例子介紹了The examples below identify the collation sequences that would be used to determine the results of text comparisons that may be performed by various SQL statements. Note that a text comparison may not be required, and no collation sequence used, in the case of numeric, blob or NULL values.
CREATE TABLE t1(
a, -- default collation type BINARY
b COLLATE BINARY, -- default collation type BINARY
c COLLATE REVERSE, -- default collation type REVERSE
d COLLATE NOCASE -- default collation type NOCASE
);
-- Text comparison is performed using the BINARY collation sequence.
SELECT (a = b) FROM t1;
-- Text comparison is performed using the NOCASE collation sequence.
SELECT (d = a) FROM t1;
-- Text comparison is performed using the BINARY collation sequence.
SELECT (a = d) FROM t1;
-- Text comparison is performed using the REVERSE collation sequence.
SELECT ('abc' = c) FROM t1;
-- Text comparison is performed using the REVERSE collation sequence.
SELECT (c = 'abc') FROM t1;
-- Grouping is performed using the NOCASE collation sequence (i.e. values
-- 'abc' and 'ABC' are placed in the same group).
SELECT count(*) GROUP BY d FROM t1;
-- Grouping is performed using the BINARY collation sequence.
SELECT count(*) GROUP BY (d || '') FROM t1;
-- Sorting is performed using the REVERSE collation sequence.
SELECT * FROM t1 ORDER BY c;
-- Sorting is performed using the BINARY collation sequence.
SELECT * FROM t1 ORDER BY (c || '');
-- Sorting is performed using the NOCASE collation sequence.
SELECT * FROM t1 ORDER BY c COLLATE NOCASE;