多數的資料庫都使用靜態欄位型態。而 SQLite 則是使用動態欄位型態。在 SQLite 一個資料的型態會根據資料本身而定,不是依所處的欄位。SQLite 的動態欄位型態可以向後相容多數的靜態欄位型態,也就是 SQLite 的 SQL 字串可以使用舊有的靜態欄位型態。
儲存類別 (Class)
在 SQLite 是依下列五種類別儲存。在 SQLite3 里的欄位(除了 INTEGER PRIMARY KEY) 都被設定成儲存任一類別,不區分類別及型態。
- NULL: 就是 NULL 值。
- INTEGER: 有號整數,欄位大小有 1,2,3,4,6,8 byte(s),依數值大小而定。
- REAL: 浮點數,欄位大小 8 bytes。
- TEXT: 不固定長度字串,字串編碼格式分 UTF-8/UTF-16BE/UTF16LE。
- BLOB: 二進制資料。
資料型態 (Dataype)
- Boolean (布林數)
布林數會儲存成 INTEGER,0 or 1。 - Date and Time (日期時間)
日期時間資料會依據 SQLite 內建的日期時間函數而存成 TEXT, REAL or INTEGER。
- TEXT
ISO8601 字串("YYYY-MM-DD HH:MM:SS.SSS)。 - REAL
Julian時間,以日為單位,計算開始時間依公曆(proleptic Gregorian),格林威治時間,西元前 4714 年 11 月 24 日中午12點起。 - INTEGER
unix 時間,以秒為單位,起始時間 1970-01-01 00:00:00 UTC。
- TEXT
相似性型態 (Type Affinity)
為了相容其它資料庫,SQLite 提供一種概念叫"欄位相似性型態"。"欄位相似性型態"是指儲存在欄位內資料的建議資料型態。重要的是型態是建議而非必需。任何欄位仍然可以儲存任何型態的資料。
在 SQLite3 的每一個欄位可以設定下列的相似型態。
- TEXT
TEXT 儲存資料是使用 NULL, TEXT, BLOB 類別。假如數值資料填入 TEXT 欄位,則會先將數值轉換成字串再存入。 - NUMERIC
NUMERIC 儲存資料是使用 NULL, INTEGER, REAL, TEXT, BLOB 所有類別。當字串資料填入 NUMERIC 欄位,如字串可以無誤差轉換成數值且可以再從數值無誤差轉換成文字,則字串會轉換成 INTEGER or REAL。若無法做到字串無差異轉換成數值,則把字串存成 TEXT。NULL 及 BLOB 資料不會做轉換,直接存入。 一個看似浮點數的字串,例如有小數點的字串或指數的字串,則轉換成數值後只是整數,NUMERIC 就會把字串轉換成 INTEGER。如 '3.0e+5' 存入 NUMERIC 欄位,會被轉成整數 300000,而非浮點數 300000.0。 - INTEGER
INTEGER 的處理方式跟 NUMERIC 一樣,唯一的不同處只在 CAST。 - REAL
REAL 的處理方式跟 NUMERIC 一樣,只差在 REAL 會把整數資料強制轉換成浮點數。(因為內部最佳化,很小的浮點數值且沒有帶小數點,在寫入硬碟會轉成換 INTEGER(為了省空間),在被讀取時會自動轉換成浮點數。這個最佳化在 SQLite 是完全看不出來,只能在計算 raw bits 才能發現。) - NONE
NONE 就是不做任何轉換動作,輸入什麼資料就存入什麼資料。
欄位型態相容性的計算,主要根據下列規則順序。注意下列規則是有順序的,比如欄位型態名稱宣告為 "FLOATING POINT" 時,是採用 "INTEGER",因為字尾 "INT" 符合第一項規則,而開頭 "FLOA" 符合第四項規則不必採納。還有 "STRING" 會被轉換成 "NUMERIC" 而非 "TEXT"。
- 型態名稱包含字串 "INT" 會被指定成 "INTEGER"。
- 型態名稱包含字串 "CAHR", "CLOB", "TEXT" 都會指定成 "TEXT"。所以 "VARCHAR" 包含 "CHAR" 也是屬於 "TEXT" 的一種。
- 型態名稱包含字串 "BLOB" 或沒有名稱則指定成 "NONE"。
- 型態名稱包含字串 "REAL", "FLOA", "DOUB" 都會指定成 "REAL"。
- 其它則都指定成 "NUMERIC"。
比較運算式 (Comparison Expressions)
SQLite3 的比較運算子(operator)包含 "=", "<", "<=", ">=", "!=", "IN", "BETWEEN", "IS"。不同儲存類別的比較,需依據下列規則。
- "NULL" 被視為比其它值都小,包含其它值也是 "NULL"。(???)
- "INTEGER" or "REAL" 被視為比 "TEXT" or "BLOB" 小。當 "INTEGER" or "REAL" 互相比較時,則根據數值比較方式。
- "TEXT" 被視為比 "BLOB" 小。當 "TEXT" 互相比較時,則會採用一個適當的排序方法。
- 當 "BLOB" 互相比較時,則依據 memcmp() 來比較。
- NULL < INTEGER, REAL < TEXT < BLOB。
SQLite 可能企圖在 INTEGER, REAL, TEXT 互相比較前轉換成相同儲存類別。
- An expression that is a simple reference to a column value has the same affinity as the column. Note that if X and Y.Z are column names, then +X and +Y.Z are considered expressions for the purpose of determining affinity.
- "CAST(expr as type)" 里的運算式(expr)則擁有 type 相似性。
- 以上二者條件都不合,則運算式則為 "NONE" 相似性。
"apply affinity" 指轉換運算元成一個特定的儲存類別,當且僅當此轉換是無損且可逆轉的。此轉換是在比較之前發生,而且根據下列規格。
- 假如運算元為 "INTEGER", "REAL", "NUMERIC",另一個運算元為 "TEXT", "NONE",則另一個運算元會被轉換成 "NUMERIC"。
- 假如運算元為 "TEXT",另一個運算元為 "NONE",則另一個運算元會被轉換成 "TEXT"。
- 以上二者條件都不合,則不做任何轉換。
"a BETWEEN b and c"會被視做二個運算式 "a>=b AND a<=c",即使這意味著不同的運算式,'a' 會有不同的 affinity。"x IN (SELECT y ...)" 被視做 "x=y",但 "a IN (x, y, z, ...)則被看做 "a=+x OR a=+y OR a=+z OR ...),也就是說 x,y,z 這些值是不會有 affinity,即使它們是欄位儲存值或使用 CAST 轉換。
參考網址 jyhshin.pixnet.net/blog/post/31988011 , www.sqlite.org/datatype3.html