資料型態

前言

大多數的 SQL 資料庫(不包含 SQLite) 使用靜態死板的欄位型態。而 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),格林威治(Greenwich)時間,西元前 4714 年 11 月 24 日中午12點起。

      • INTEGER

        • unix 時間,以秒為單位,起始時間 1970-01-01 00:00:00 UTC。

相似性型態 (Type Affinity)

為了相容其它資料庫,SQLite 提供一種概念叫"欄位相似性型態"。"欄位相似性型態"是指儲存在欄位里資料的建議資料型態。最重要的觀念是型態是建議而非必需。任何欄位仍然可以儲存任何型態的資料。

在 SQLite3 的每一個欄位可以設定下列的相似性型態。

    • TEXT

    • TEXT 儲存資料是使用 NULL, TEXT, BLOB 類別。假如數值資料填入 TEXT 欄位,則會先將數值轉換成字串再存入。

    • NUMERIC

    • NUMERIC 儲存資料是使用 NULL, INTEGER, REAL, TEXT, BLOB 所有類別。當字串資料填入 NUMERIC 欄位,假如字串可以無誤差轉換成數值且可以再從數值無誤差轉換成文字,則字串會轉換成 INTEGER or REAL。如果無法做到字串無損轉換成數值,則把字串存成 TEXT。NULL 及 BLOB 資料不會做轉換,直接存入。<br /> 一個看起來像浮點數的字串,比如帶有小數點的字串或用指數表示的字串,轉換成數值後只是整數,NUMERIC 會把字串轉換成 INTEGER。比如 '3.0e+5' 存入 NUMERIC 欄位,會被轉成整數 300000,而非浮點數 300000.0。

    • INTEGER

    • INTEGER 的處理方式跟 NUMERIC 一樣,唯一的不同處只在 CAST expression(???)。

    • REAL

    • REAL 的處理方式跟 NUMERIC 一樣,只差別在 REAL 會把整數資料強制轉換成浮點數。(因為內部最佳化,很小的浮點數值且沒有帶小數點,在寫入硬碟會轉成換 INTEGER(為了省空間),在被讀取時會自動轉換成浮點數。這個最佳化在 SQLite 是完全看不出來,只能在計算 raw bits 才能發現。)

    • NONE

    • NONE 就是不做任何轉換動作,輸入什麼資料就存入什麼資料。

欄位型態相容性的計算,主要根據下列的規則順序。注意下列規則是有順序的,比如欄位型態名稱宣告為 "FLOATING POINT" 時,是採用 "INTEGER",因為字尾 "INT" 符合第一項規則,而開頭 "FLOA" 符合第四項規則不必採納。還有 "STRING" 會被轉換成 "NUMERIC" 而非 "TEXT"。

    1. 型態名稱包含字串 "INT" 會被指定成 "INTEGER"。

    2. 型態名稱包含字串 "CAHR", "CLOB", "TEXT" 都會指定成 "TEXT"。所以 "VARCHAR" 包含 "CHAR" 也是屬於 "TEXT" 的一種。

    3. 型態名稱包含字串 "BLOB" 或沒有名稱則指定成 "NONE"。

    4. 型態名稱包含字串 "REAL", "FLOA", "DOUB" 都會指定成 "REAL"。

    5. 其它則都指定成 "NUMERIC"。

比較運算式 (Comparison Expressions)

SQLite3 的比較運算子(operator)包含 "=", "<", "<=", ">=", "!=", "IN", "BETWEEN", "IS"。不同儲存類別的比較,需依據下列規則。

    1. "NULL" 被視為比其它值都小,包含其它值也是 "NULL"。(???)

    2. "INTEGER" or "REAL" 被視為比 "TEXT" or "BLOB" 小。當 "INTEGER" or "REAL" 互相比較時,則根據數值比較方式。

    3. "TEXT" 被視為比 "BLOB" 小。當 "TEXT" 互相比較時,則會採用一個適當的排序方法。

    4. 當 "BLOB" 互相比較時,則依據 memcmp() 來比較。

    5. NULL < INTEGER, REAL < TEXT < BLOB。

SQLite 可能企圖在 INTEGER, REAL, TEXT 互相比較前轉換成相同儲存類別。

    1. (??? 看嘸)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.

    2. "CAST(expr as type)" 里的運算式(expr)則擁有 type 相似性。

    3. 以上二者條件都不合,則運算式則為 "NONE" 相似性。

"apply affinity" 指轉換運算元成一個特定的儲存類別,當且僅當此轉換是無損且可逆轉的。此轉換是在比較之前發生,而且根據下列規格。

    1. 假如運算元為 "INTEGER", "REAL", "NUMERIC",另一個運算元為 "TEXT", "NONE",則另一個運算元會被轉換成 "NUMERIC"。

    2. 假如運算元為 "TEXT",另一個運算元為 "NONE",則另一個運算元會被轉換成 "TEXT"。

    3. 以上二者條件都不合,則不做任何轉換。

"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 轉換。

資料來源:http://www.sqlite.org/datatype3.html