1.概述 我們熟知的資料庫引擎大部分採用靜態數據類型,即列定義的類型定義了值的存儲,並且值要嚴格滿足列的定義,同一列所有值的存儲方式都相同,比如定義了一個列類型為整型 int,不能在該列上輸入'abc'。SQLite的數據類型則採用了動態類型,列定義不能決定值的存儲,值的存儲由值本身決定,因此在.....
1.概述
我們熟知的資料庫引擎大部分採用靜態數據類型,即列定義的類型定義了值的存儲,並且值要嚴格滿足列的定義,同一列所有值的存儲方式都相同,比如定義了一個列類型為整型 int,不能在該列上輸入'abc'。SQLite的數據類型則採用了動態類型,列定義不能決定值的存儲,值的存儲由值本身決定,因此在SQLite中,同一列會有多種存儲方式。
2.數據類型與存儲類
SQLite根據值的存儲劃分為以下幾種存儲類型:
存儲類別 | 含義 |
NULL | 表示該值為NULL |
INTEGER | 有符號整型值,根據值大小控制存儲占用的位元組數,可能為1,2,3,4,6 or 8個位元組 |
REAL | 浮點值,採用8個位元組存儲,實質是採用double存儲,有效數字為15位 |
TEXT | 文本字元串,存儲使用的編碼方式為UTF-8、UTF-16BE、UTF-16LE,預設最大可以存儲1G個位元組 |
BLOB | 存儲二進位數據,預設最大可以存儲1G個位元組 |
在SQLite中,存儲分類和數據類型不是完全等價的,如INTEGER存儲類別可以包含6種不同長度的Integer數據類型,然而這些INTEGER數據一旦被讀入到記憶體後,SQLite會將其全部視為占用8個位元組有符號整型。因此對於SQLite而言,同一個欄位類型,可以在該欄位中存儲不停類型的數據,而且即便值的存儲類型相同,底層存儲占用的空間也與值相關,比如有的INTEGER占用1個位元組,有的INTEGER可能占用8個位元組。
(1).布爾數據類型:
SQLite並沒有提供專門的布爾存儲類型,取而代之的是存儲整型1表示true,0表示false。
(2).日期和時間數據類型:
和布爾類型一樣,SQLite也同樣沒有提供專門的日期時間存儲類型,而是以TEXT、REAL和INTEGER類型分別不同的格式表示該類型,如:
TEXT: "YYYY-MM-DD HH:MM:SS.SSS"
REAL: 以Julian日期格式存儲
INTEGER: 以Unix時間形式保存數據值,即從1970-01-01 00:00:00到當前時間所流經的秒數。
SQLite提供typeof函數,用戶可以根據這個函數來確定給定值的存儲類型。
3.類型親緣性
為了最大化SQLite和其它資料庫引擎之間的數據類型相容性,SQLite提出了"類型親緣性(Type Affinity)"的概念。我們可以這樣理解"類型親緣性 ",在表欄位被聲明之後,SQLite都會根據該欄位聲明時的類型為其選擇一種親緣類型,當數據插入時,該欄位的數據將會優先採用親緣類型作為該值的存儲方式,除非親緣類型不匹配或無法轉換當前數據到該親緣類型,這樣SQLite才會考慮其它更適合該值的類型存儲該值。SQLite目前的版本支持以下五種親緣類型:
親緣類型 | 描述 |
TEXT | 數值型數據在被插入之前,需要先被轉換為文本格式,之後再插入到目標欄位中。 |
NUMERIC | 當文本數據被插入到親緣性為NUMERIC的欄位中時,如果轉換操作不會導致數據信息丟失以及完全可逆,那麼SQLite就會將該文本數據轉換為INTEGER或REAL類型的數據,如果轉換失敗,SQLite仍會以TEXT方式存儲該數據。對於NULL或BLOB類型的新數據,SQLite將不做任何轉換,直接以NULL或BLOB的方式存儲該數據。需要額外說明的是,對於浮點格式的常量文本,如"30000.0",如果該值可以轉換為INTEGER同時又不會丟失數值信息,那麼SQLite就會將其轉換為INTEGER的存儲方式。 |
INTEGER | 對於親緣類型為INTEGER的欄位,其規則等同於NUMERIC,唯一差別是在執行CAST表達式時。 |
REAL | 其規則基本等同於NUMERIC,唯一的差別是不會將"30000.0"這樣的文本數據轉換為INTEGER存儲方式。 |
NONE | 不做任何的轉換,直接以該數據所屬的數據類型進行存儲。 |
3.1.欄位親緣性的規則
欄位的親緣性是根據該欄位在聲明時被定義的類型來決定的,具體的規則可以參照以下列表。需要註意的是以下列表的順序,即如果某一欄位類型同時符合兩種親緣性,那麼排在前面的規則將先產生作用。
1). 如果類型字元串中包含"INT",那麼該欄位的親緣類型是INTEGER。
2). 如果類型字元串中包含"CHAR"、"CLOB"或"TEXT",那麼該欄位的親緣類型是TEXT,如VARCHAR。
3). 如果類型字元串中包含"BLOB",那麼該欄位的親緣類型是NONE。
4). 如果類型字元串中包含"REAL"、"FLOA"或"DOUB",那麼該欄位的親緣類型是REAL。
5). 其餘情況下,欄位的親緣類型為NUMERIC。
3.2.具體示例
聲明類型 | 親緣類型 | 應用規則 |
INT INTEGER TINYINT SMALLINT MEDIUMINT BIGINT UNSIGNED BIG INT INT2 INT8 |
INTEGER | 1 |
CHARACTER(20) VARCHAR(255) VARYING CHARACTER(255) NCHAR(55) NATIVE CHARACTER(70) NVARCHAR(100) TEXT CLOB |
TEXT | 2 |
BLOB | NONE | 3 |
REAL DOUBLE DOUBLE PRECISION FLOAT |
REAL | 4 |
NUMERIC DECIMAL(10,5) BOOLEAN DATE DATETIME |
NUMERIC | 5 |
4.比較與排序
在SQLite3中支持的比較表達式有:"=", "==", "<", "<=", ">", ">=", "!=", "<>", "IN", "NOT IN", "BETWEEN", "IS" and "IS NOT"。數據的比較結果主要依賴於操作數的存儲方式,其規則為:
1). 存儲方式為NULL的數值小於其它存儲類型的值。
2). 存儲方式為INTEGER和REAL的數值小於TEXT或BLOB類型的值,如果同為INTEGER或REAL,則基於數值規則進行比較。
3). 存儲方式為TEXT的數值小於BLOB類型的值。
4). 如果是兩個BLOB類型的數值進行比較,其結果為C運行時函數memcmp()的結果。
5). 如果同為TEXT,SQLite利用特定的比較規則來判斷,支持3種比較規則:
校對規則 | 含義 |
binary | 比較字元串採用memcmp(),無論字元串是哪種編碼 |
nocase | 與binary類似,但忽略大小寫 |
rtrim | 與binary類似,但忽略字元串末尾的空格 |
通過建表語句在可以在指定列上指定校對規則,比如:
CREATE TABLE t1( x INTEGER PRIMARY KEY, a, /* collating sequence BINARY */ b COLLATE BINARY, /* collating sequence BINARY */ c COLLATE RTRIM, /* collating sequence RTRIM */ d COLLATE NOCASE /* collating sequence NOCASE */ );
5.參考文檔
https://www.sqlite.org/datatype3.html
http://www.cnblogs.com/stephen-liu74/archive/2012/01/18/2325258.html