SQLite 是「無型態」的。這表示您可以將任何類型的資料儲存在任何資料表的任何欄位中,而與該欄位的宣告資料型態無關。(請參閱下方第 2.0 節中的例外規則。)這種行為是一種特色,而不是錯誤。資料庫應該儲存和擷取資料,資料的格式對資料庫來說不重要。在多數其他 SQL 引擎中找到並在 SQL 語言規格中編纂的強型態系統是一個錯誤的功能,這是實作顯示在介面中的範例。SQLite 允許您將任何類型的資料儲存在任何類型的欄位中,並允許在資料型態的規格中彈性調整,以克服這個錯誤的功能。
對 SQLite 而言,資料型態是零個或多個名稱的任何順序,後面可選擇加上一個或兩個有號整數的括號清單。特別注意,資料型態可能是零個或多個名稱。這表示空字串就 SQLite 而言是一個有效的資料型態。因此,您可以宣告資料表的每個欄位的資料型態未指定,如下所示
CREATE TABLE ex1(a,b,c);
即使 SQLite 允許省略資料型態,仍建議您將其包含在 CREATE TABLE 陳述式中,因為資料型態通常可以作為提示,讓其他程式設計師了解您打算將什麼放入欄位中。而且,如果您將程式碼移植到其他資料庫引擎,該其他引擎可能會需要某種資料型態。SQLite 接受所有常見的資料型態。例如
CREATE TABLE ex2( a VARCHAR(10), b NVARCHAR(15), c TEXT, d INTEGER, e FLOAT, f BOOLEAN, g CLOB, h BLOB, i TIMESTAMP, j NUMERIC(10,5) k VARYING CHARACTER (24), l NATIONAL VARYING CHARACTER(16) );
等等。基本上,任何名稱順序,後面可選擇加上括號中的兩個有號整數,都可以使用。
SQLite 無類型的例外之一是類型為 INTEGER PRIMARY KEY 的欄位。(而且您必須使用「INTEGER」,而不是「INT」。類型為 INT PRIMARY KEY 的欄位與其他欄位一樣無類型。)INTEGER PRIMARY KEY 欄位必須包含 32 位元有號整數。任何嘗試插入非整數資料的動作都會導致錯誤。
INTEGER PRIMARY KEY 欄位可用於實作等同於 AUTOINCREMENT 的功能。如果您嘗試將 NULL 插入 INTEGER PRIMARY KEY 欄位,該欄位實際上會填入一個整數,該整數比表格中已存在的最大金鑰大 1。或者,如果最大金鑰為 2147483647,則該欄位會填入一個隨機整數。不論哪種方式,INTEGER PRIMARY KEY 欄位都會被指定一個唯一的整數。您可以使用 sqlite_last_insert_rowid() API 函數或在後續 SELECT 陳述式中使用 last_insert_rowid() SQL 函數來擷取此整數。
SQLite 在決定允許儲存在欄位中的資料時是無類型的。但在排序和比較資料時,會用到一些類型的概念。在這些目的中,欄位或表達式可以是下列兩種類型之一:數字和文字。排序或比較可能會產生不同的結果,具體取決於正在排序或比較的資料類型。
如果資料類型為文字,則比較會由標準 C 資料比較函數 memcmp() 或 strcmp() 決定。比較會逐一檢視兩個輸入的位元組,並傳回第一個非零差異。字串會以 '\000' 結束,因此較短的字串會排在較長的字串之前,正如您所預期的。
對於數字資料,這個情況比較複雜。如果兩個輸入看起來像格式良好的數字,則使用 atof() 將它們轉換為浮點值並進行數字比較。如果一個輸入不是格式良好的數字,但另一個輸入是,則數字被認為小於非數字。如果沒有輸入是格式良好的數字,則使用 strcmp() 進行比較。
不要被一欄可能具有「數字」資料類型的事實所混淆。這並不表示該欄只能包含數字。這僅表示如果該欄確實包含數字,則該數字將按數字順序排序。
對於文字和數字值,NULL 排序在任何其他值之前。使用「<」或「>=」等運算子將任何值與 NULL 進行比較總是錯誤的。
對於 SQLite 版本 2.6.3 及更早版本,所有值都使用數字資料類型。文字資料類型出現在版本 2.7.0 及更高版本中。在後續部分中,假設您使用的是 SQLite 的版本 2.7.0 或更高版本。
對於表達式,結果的資料類型通常由最外層運算子決定。例如,算術運算子(「+」、「*」、「%」)總是傳回數字結果。字串串接運算子(「||」)傳回文字結果。以此類推。如果您對表達式的資料類型有任何疑問,可以使用特殊的 typeof() SQL 函數來判定資料類型。例如
sqlite> SELECT typeof('abc'+123); numeric sqlite> SELECT typeof('abc'||123); text
對於資料表欄,資料類型由 CREATE TABLE 陳述式的類型宣告決定。當且僅當類型宣告包含下列字串之一或多個時,資料類型為文字
BLOB
CHAR
CLOB
TEXT
當然,在類型宣告中搜尋這些字串時不分大小寫。如果上述任一字串出現在類型宣告中的任何地方,則該欄位的資料類型為文字。請注意「VARCHAR」類型包含「CHAR」作為子字串,因此它被視為文字。
如果上述任一字串未出現在類型宣告中的任何地方,則資料類型為數字。特別注意,具有空類型宣告的欄位的資料類型為數字。
考慮以下兩個指令序列
CREATE TABLE t1(a INTEGER UNIQUE); CREATE TABLE t2(b TEXT UNIQUE); INSERT INTO t1 VALUES('0'); INSERT INTO t2 VALUES(0); INSERT INTO t1 VALUES('0.0'); INSERT INTO t2 VALUES(0.0);
在左邊的序列中,第二個插入會失敗。在此情況下,字串「0」和「0.0」被視為數字,因為它們被插入到數字欄位中,但 0==0.0,這會違反唯一性約束。然而,右邊序列中的第二個插入會成功。在此情況下,常數 0 和 0.0 被視為字串,這表示它們是不同的。
為了比較的目的,SQLite 總是將數字轉換為雙精度 (64 位元) 浮點數。這表示一連串僅在不顯著位元不同的數字,如果它們在數字欄位中,則會比較相等,但如果它們在文字欄位中,則會比較不相等。我們有
INSERT INTO t1 INSERT INTO t2 VALUES('12345678901234567890'); VALUES(12345678901234567890); INSERT INTO t1 INSERT INTO t2 VALUES('12345678901234567891'); VALUES(12345678901234567891);
與之前相同,左邊的第二個插入會失敗,因為比較會先將兩個字串轉換為浮點數,而字串中唯一的差異在第 20 位元,這超過了 64 位元浮點數的解析度。相反地,右邊的第二個插入會成功,因為在這種情況下,插入的數字是字串,並使用 memcmp() 進行比較。
數字和文字類型也會對 DISTINCT 關鍵字造成影響
CREATE TABLE t3(a INTEGER); CREATE TABLE t4(b TEXT); INSERT INTO t3 VALUES('0'); INSERT INTO t4 VALUES(0); INSERT INTO t3 VALUES('0.0'); INSERT INTO t4 VALUES(0.0); SELECT DISTINCT * FROM t3; SELECT DISTINCT * FROM t4;
左邊的 SELECT 陳述式會傳回單一列,因為「0」和「0.0」被視為數字,因此不分明。但右邊的 SELECT 陳述式會傳回兩列,因為 0 和 0.0 被視為不同的字串。
此頁面最後修改於 2022-01-08 05:02:57 UTC