SQLite3的數據類型-動態數據類型
1. SQLite中的數據類型
大多數SQL數據庫引擎(除了SQLite之外的每個SQL數據庫引擎,據我們所知)都使用靜態,嚴格的類型。使用靜態類型時,列的數據類型由其容器(存儲值的特定列)確定。
SQLite使用更通用的動態類型系統。在SQLite中,值的數據類型與值本身相關聯,而不是與其容器相關聯。SQLite的動態類型系統向后兼容其他數據庫引擎的更常見的靜態類型系統,因為在靜態類型數據庫上工作的SQL語句應該在SQLite中以相同的方式運行。但是,SQLite中的動態類型允許它執行傳統的剛性類型數據庫中無法實現的操作。
2. 存儲類和數據類型
存儲在SQLite數據庫中(或由數據庫引擎操縱)的每個值都是以下存儲類之一:
- NULL。該值為NULL值。
- INTEGER。該值是有符號整數,存儲為1,2,3,4,6或8個字節,具體取決于值的大小。
- REAL。該值是浮點值,存儲為8字節IEEE浮點數。
- TEXT。該值是一個文本字符串,使用數據庫編碼(UTF-8,UTF-16BE或UTF-16LE)存儲。
- BLOB。該值是一個數據塊,可以二進制的形式存儲任何數據。
存儲類比數據類型更通用。例如,INTEGER存儲類包括6種不同長度的不同整數數據類型。這在磁盤上有所不同。但是一旦從磁盤讀取INTEGER值并進入內存進行處理,它們就會轉換為最通用的數據類型(8字節有符號整數)。因此,在大多數情況下,“存儲類”與“數據類型”無法區分,并且這兩個術語可以互換使用。
除了INTEGER PRIMARY KEY列之外,SQLite版本3數據庫中的任何列都可用于存儲任何存儲類的值。
SQL語句中的所有值,無論是嵌入在SQL語句文本中的文字還是綁定到預編譯SQL語句的參數, 都具有隱式存儲類。在下面描述的情況下,數據庫引擎可以在查詢執行期間在數值存儲類(INTEGER和REAL)和TEXT之間轉換值。
(1) 布爾數據類型
SQLite沒有單獨的布爾存儲類。相反,布爾值存儲為整數0(假)和1(真)。
(2) 日期和時間數據類型
SQLite沒有為存儲日期和/或時間而預留的存儲類。相反,SQLite 的內置日期和時間函數能夠將日期和時間存儲為TEXT,REAL或INTEGER值:
- TEXT為ISO8601字符串(“YYYY-MM-DD HH:MM:SS.SSS”)。
- REAL如朱利安日數,根據公歷4714年11月24日格林威治中午以來的天數。
- INTEGER as Unix Time,自1970-01-01 00:00:00 UTC以來的秒數。
應用程序可以選擇以任何這些格式存儲日期和時間,并使用內置的日期和時間函數在格式之間自由轉換 。
3. Type Affinity
使用嚴格類型的SQL數據庫引擎通常會嘗試自動將值轉換為適當的數據類型。考慮一下:
- CREATE TABLE t1(a INT, b VARCHAR(10));
- INSERT INTO t1(a,b) VALUES('123',456);
在執行插入之前,剛性類型的數據庫將字符串'123'轉換為整數123,將整數456轉換為字符串'456'。
為了最大化SQLite和其他數據庫引擎之間的兼容性,上面的示例將像在其他SQL數據庫引擎上一樣對SQLite起作用,SQLite支持列上的“類型親和性”概念。列的類型親緣關系是存儲在該列中的數據的推薦類型。這里的重要思想是建議使用類型,而不是必需的。任何列仍然可以存儲任何類型的數據。根據選擇,某些列更傾向于使用一個存儲類而不是另一個存儲類。列的首選存儲類稱為“親和性”。
SQLite 3數據庫中的每一列都分配了以下類型之一:
- TEXT
- NUMERIC
- INTEGER
- REAL
- BLOB
(歷史記錄:“BLOB”類型的親和力曾被稱為“NULL”。但該術語容易與“無親和力”混淆,因此它被重命名。)
具有TEXT親緣關系的列使用存儲類NULL,TEXT或BLOB存儲所有數據。如果將數值數據插入到具有TEXT親和力的列中,則在存儲之前將其轉換為文本形式。
具有NUMERIC親緣關系的列可能包含使用所有五個存儲類的值。當文本數據插入NUMERIC列時,如果此類轉換是無損且可逆的,則文本的存儲類將轉換為INTEGER或REAL(按優先順序)。對于TEXT和REAL存儲類之間的轉換,如果保留數字的前15個有效十進制數字,SQLite認為轉換是無損且可逆的。如果無法將TEXT無損轉換為INTEGER或REAL,則使用TEXT存儲類存儲該值。不嘗試轉換NULL或BLOB值。
字符串可能看起來像帶有小數點和/或指數表示法的浮點字面值,但只要該值可以表示為整數,NUMERIC親和關系就會將其轉換為整數。因此,字符串'3.0e + 5'存儲在具有NUMERIC親和度作為整數300000的列中,而不是作為浮點值300000.0。
使用INTEGER關聯的列與具有NUMERIC關聯的列的行為相同。INTEGER和NUMERIC親和力之間的區別僅在CAST表達式中很明顯。
具有REAL親和性的列的行為類似于具有NUMERIC親和力的列,除了它將整數值強制為浮點表示形式。(作為內部優化,沒有小數組件并存儲在具有REAL關聯性的列中的小浮點值將作為整數寫入磁盤,以便占用更少的空間,并在讀取值時自動轉換回浮點。優化在SQL級別完全不可見,只能通過檢查數據庫文件的原始位來檢測。)
具有關聯性BLOB的列不優選一個存儲類而不是另一個存儲類,并且不會嘗試將數據從一個存儲類強制轉換為另一個存儲類。