SQLite數據類型

大多數 SQL 數據庫引擎(據咱們所知,除 SQLite 以外的全部SQL 數據庫引擎)都使用嚴格的靜態類型。使用靜態類型,值的類型便由它的容器 --存儲值的特定的列 --來決定。sql

SQLite 使用更通用的動態類型系統。在SQLit 中,值的數據類型與值自己相關,而不是與它的容器。SQLite的動態類型系統與其它數據庫引擎的經常使用靜態類型系統是向後兼容的,在這個意義上,工做在靜態類型數據庫上的SQL 語句應該以一樣的方式工做在SQLite 中。然而,SQLite中的動態類型容許它作傳統的嚴格類型的數據庫所不能作的事。數據庫

1.0 存儲類型與數據類型app

存儲在 SQLite 數據庫中的每一個值(或是由數據庫引擎所操做的值)都有一個如下的存儲類型:less

1     NULL. 值是空值。ide

2     INTEGER. 值是有符號整數,根據值的大小以12346 8字節存儲。函數

3     REAL. 值是浮點數,以8字節IEEE 浮點數存儲。優化

4     TEXT. 值是文本字符串,使用數據庫編碼(UTF-8,UTF-16BE UTF-16LE)進行存儲。this

5     BLOB. 值是一個數據塊,按它的輸入原樣存儲。編碼

注意,存儲類型比數據類型更籠統。以 INTEGER 存儲類型爲例,它包括6種不一樣的長度不等的整數類型,這在磁盤上是不一樣的。可是隻要INTEGER 值從磁盤讀取到內存進行處理,它們就被轉換爲更爲通常的數據類型(8字節有符號整型)。所以在通常狀況下,存儲類型數據類型沒什麼差異,這兩個術語能夠互換使用。url

SQLite 版本3數據庫中的任何列,除了整型主鍵列,均可用於存儲任何存儲類型的值。

SQL 語句中的任何值,不管它們是嵌入到SQL 語句中的字面量仍是綁定到預編譯SQL 語句中的參數,都有一個隱含的存儲類型。在下述狀況下,數據庫引擎會在執行查詢時在數值存儲類型(INTEGERREAL)和TEXT 之間進行轉換。

1.1 布爾類型

SQLite 並無單獨的布爾存儲類型,而是將布爾值存儲爲整數 0(false) 1(true)

1.2 日期和時間類型

SQLite 沒有另外的存儲類型來存儲日期和時間。SQLite的內置的日期和時間函數可以將日期和時間存爲TEXTREALINTEGER 值:

1     TEXT  ISO8601 字符串 ("YYYY-MM-DD HH:MM:SS.SSS")

2     REAL 儒略日數(Julian Day Numbers),按照前公曆,自格林威治時間公元前47141124日中午以來的天數。

3     INTEGER Unix 時間,自1970-01-01 00:00:00 UTC 以來的秒數。

應用能夠選擇這些格式中的任一種存儲日期和時間,並使用內置的日期和時間函數在這些格式間自由轉換。

2.0 類型親和性

爲了最大限度地提升 SQLite 和其它數據庫引擎之間的兼容性,SQLite支持列的類型親和性的概念。列的類型親和性是指數據存儲於該列的推薦類型。這裏重要的思想是類型是推薦的,而不是必須的。任何列仍能夠存儲任何類型的數據。這只是讓一些列有選擇性地優先使用某種存儲類型。一個列的首選存儲類型被稱爲它的親和性

每一個 SQLite 3 數據庫中的列都歸於如下的類型親和性中的一種:

1     TEXT

2     NUMERIC

3     INTEGER

4     REAL

5     NONE

一個具備 TEXT 親和性的列使用存儲類型 NULLTEXT BLOB 存儲全部數據。若是數值數據被插入到一個具備TEXT 親和性的列,則數據在存儲前被轉換爲文本形式。

數值親和性的列可能包含了使用全部五個存儲類的值。當插入文本數據到數值列時,該文本的存儲類型被轉換成整型或實數(按優先級排序)若是這種轉換是無損或可逆的的話。對於文本與實數類型之間的轉換,若是前15個重要十進制數字被保留的話,SQLite認爲這種轉換是無損並可逆的。若是文本不能無損地轉換成整型或實數,那這個值將以文本類型存儲。不要試圖轉換NULLBLOB值。

一個字符串可能看上去像帶有小數點和/或指數符的浮點文字,但只要這個值能夠用一個整型表示,數值親和性就會把它轉換成一個整型。所以,字符串‘3.0e+5'以整型300000,而不是浮點值30000.0的形式存儲在一個數值親和性的列裏。

 

一個使用整型親和性的列與具備數值親和性的列表現一致。只是在CAST表達式裏,它們之間的區別體現得明顯。

除了強制將整型值轉換成浮點表示外,一個具備實數親和性的列與具備數值親和性的列表現一致(做爲一個內部的優化,爲了少佔用空間,無小數部分且存儲在實數親和性列上的小浮點值以整型形式寫到磁盤,讀出時自動轉換回浮點值。在SQL級別,這種優化是徹底不可見的,而且只能經過檢查數據庫文件的原始比特檢測到)。

一個具備NONE親和性的列不能從一種存儲類型轉換成另外一種,也不要試圖強制對它進行轉換。

2.1 列親和性測定

列的親和性是由它的聲明類型決定的,按照如下順序所示的規則:

1. 若是聲明類型包含字符串「INT」,那它被指定爲整型親和性;

2. 若是列的聲明類型包含任何「CHAR」「CLOB」「TEXT」字符串,那麼該列具備文本親和性。注意:VARCHAR類型包含「CHAR」而且被指定爲文本親和性;

3. 若是列的聲明類型包含「BLOB」或者沒有指定類型,那這列具備NONE親和性;

4. 若是列的聲明類型包含任何「REAL」「FLOA」「DOUB」字符串,則該列具備實數親和性;

5. 不然,它將具備數值親和性。

注意:斷定列親和性規則的順序是很重要的。一個具備「CHARINT」聲明類型的列將匹配規則12,可是規則1優先全部該列具備整型親和性。

2.2 親和性名字實例

下表顯示了有多少從更傳統的SQL實現的經常使用數據類型名,經過上一節介紹的五個規則被轉換成各類親和性類型。這張表只顯示了SQLite可接受的一小部分數據類型名。注意:跟在類型名後,括號內數值參數(如:VARCHAR255))將被SQLite忽略 -SQLite不對字符串、BLOBs或數值的長度強加任何限制(除了大型全局SQLITE_MAX_LENGTH限制)。

spacer.gif

注意:由於在「POINT」末尾的「INT」,一個「 FLOATING POINT」聲明類型會被賦予整型親和性,而不是實數親和性。並且「STRING」聲明類型具備數值親和性,而不是文本親和性。

2.3 列親和性行爲實例

如下SQL演示當有值插入到一張表時,SQLite如何使用列親和性實現類型轉換的:

 

?

1

2

3

4

5

6

7

CREATE TABLE  t1(

  t  TEXT,   -- text affinity by rule 2

  nu  NUMERIC, --  numeric affinity by rule 5

  i  INTEGER, --  integer affinity by rule 1

  r  REAL,   -- real affinity by rule 4

  no BLOB   --  no affinity by rule 3

);

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

-- Values stored as TEXT, INTEGER, INTEGER, REAL, TEXT.(值分別以文本、整型、整型、實數、文本形式存儲)

INSERT INTO  t1 VALUES('500.0',  '500.0', '500.0',  '500.0', '500.0');

SELECT typeof(t), typeof(nu), typeof(i),  typeof(r), typeof(no) FROM t1;

text|integer|integer|real|text

  

-- Values stored as TEXT, INTEGER, INTEGER, REAL, REAL.

DELETE FROM  t1;

INSERT INTO  t1 VALUES(500.0, 500.0, 500.0,  500.0, 500.0);

SELECT typeof(t), typeof(nu), typeof(i),  typeof(r), typeof(no) FROM t1;

text|integer|integer|real|real

  

-- Values stored as TEXT, INTEGER, INTEGER, REAL, INTEGER.

DELETE FROM  t1;

INSERT INTO  t1 VALUES(500, 500, 500, 500, 500);

SELECT typeof(t), typeof(nu), typeof(i),  typeof(r), typeof(no) FROM t1;

text|integer|integer|real|integer

  

-- BLOBs are always stored as BLOBs regardless of column affinity.  DELETE FROM t1;

INSERT INTO  t1 VALUES(x'0500',  x'0500', x'0500',  x'0500', x'0500');

SELECT typeof(t), typeof(nu), typeof(i),  typeof(r), typeof(no) FROM t1;

blob|blob|blob|blob|blob

  

-- NULLs are also unaffected by affinity

DELETE FROM  t1;

INSERT INTO  t1 VALUES(NULL,NULL,NULL,NULL,NULL);

SELECT typeof(t), typeof(nu), typeof(i),  typeof(r), typeof(no) FROM t1;

null|null|null|null|null

3.0 比較表達式

同標準SQL同樣,SQLite 3支持以下的比較操做符:"=","==", "<", "<=", ">",">=", "!=", "<>", "IN","NOT IN", "BETWEEN", "IS", 以及"IS NOT"

3.1 排序規則

比較的結果與操做數的存儲類型有關,同時依據如下的規則:

1     NULL值小於其餘任何值(包括另一個NULL

2     INTEGERREAL小於TEXTBLOB值;若兩個INTEGER(或者REAL)比較,則按照實際的數值進行。

3     TEXT小於BLOB,若兩個TEXT比較,結果則由適當的整理順序決定

4     若兩個BLOD比較,與memcmp()的結果一致

3.2 操做數進行比較時的類似性

在進行值的比較以前,SQLite會嘗試在存儲類INTEGERREAL/TEXT之間進行值的轉換。在比較以前嘗不嘗試進行轉換徹底取決於操做數的類似性。操做數類似性的斷定規則以下:

1     只是對一個列中的值進行引用的表達式同被引用的列具備徹底相同的類似性。注意,若是XY.Z表明的是列的名稱,那麼+X+Y.Z能夠認爲是爲了斷定其類似性的表達式。

2     "CAST(expr AS type)"所表示的表達式同類型定義爲"type"的列具備徹底相同的類似性。

3     其它狀況下的表達式具備NONE類似性。

 

3.3 比較前的類型轉換

應用類似性"applyaffinity")的意思是,當且僅當所涉及的轉換是無損且可逆的狀況下,將一個操做數轉換爲某特定的存儲類型。在進行比較以前對比較運算符的操做數應用類似性的規則以下按順序所示:

1     若是其中的一個操做數具備INTEGERREAL或者NUMERIC類似性而另一個操做數具備TEXT或者NONE類似性,那麼就要對這另一個操做數應用NUMERIC類似性。

2     若是其中的一個操做數具備TEXT類似性而另一個具備NONE類似性,那麼就要對這另一個操做數應用TEXT類似性。

3     其它狀況下不會應用任何類似性,兩個操做數按照各自的原樣進行比較。

將表達式"a BETWEEN b AND c"看做兩個單獨的二元比較運算"a>= b AND a <= c",即便這麼一來,可能會形成其中的a在兩次比較中會被應用不一樣的類似性,也要這麼處理。Datatypeconversions in comparisons of the form "x IN (SELECT y ...)"這種形式的比較中,數據類型的轉換徹底同"x=y"同樣進行處理。表達式"aIN (x, y, z, ...)" "a = +x OR a = +y OR a = +z OR ..."等價。換句話說,IN運算符右側的值(本例中就是"x","y", and "z")被看做是無類似性的,即便它們湊巧是某列的值或者是CAST表達式。

3.4 比較示例 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

CREATE TABLE  t1(

  a  TEXT,   -- text affinity

  b  NUMERIC-- numeric affinity

  c  BLOB,   -- no affinity

  d       -- no affinity

);

  

-- Values will be stored as TEXT, INTEGER, TEXT, and INTEGER  respectively

INSERT INTO  t1 VALUES('500',  '500', '500',  500);

SELECT typeof(a), typeof(b), typeof(c),  typeof(d) FROM t1;

text|integer|text|integer

  

-- Because column "a" has text affinity, numeric values on the

-- right-hand side of the comparisons are converted to text before

-- the comparison occurs.

SELECT a < 40,  a < 60,  a <  600 FROM t1;

0|1|1

  

-- Text affinity is applied to the right-hand operands but since

-- they are already TEXT this is a no-op; no conversions occur.

SELECT a < '40',  a < '60', a < '600'  FROM t1;

0|1|1

  

-- Column "b" has numeric affinity and so numeric affinity is  applied

-- to the operands on the right. Since the operands are already numeric,

-- the application of affinity is a no-op; no conversions occur. All

-- values are compared numerically.

SELECT b < 40,  b < 60,  b <  600 FROM t1;

0|0|1

  

-- Numeric affinity is applied to operands on the right, converting them

-- from text to integers. Then a numeric comparison occurs.

SELECT b < '40',  b < '60', b < '600'  FROM t1;

0|0|1

  

-- No affinity conversions occur. Right-hand side values all have

-- storage class INTEGER which are always less than the TEXT values

-- on the left.

SELECT c < 40,  c < 60,  c <  600 FROM t1;

0|0|0

  

-- No affinity conversions occur. Values are compared as TEXT.

SELECT c < '40',  c < '60', c < '600'  FROM t1;

0|1|1

  

-- No affinity conversions occur. Right-hand side values all have

-- storage class INTEGER which compare numerically with the INTEGER

-- values on the left.

SELECT d < 40,  d < 60,  d <  600 FROM t1;

0|0|1

  

-- No affinity conversions occur. INTEGER values on the left are

-- always less than TEXT values on the right.

SELECT d < '40',  d < '60', d < '600'  FROM t1;

1|1|1

若示例中的比較被替換——例如"a<40"被寫做"40>a"——全部的結果依然相同相同。

4.0 操做符

全部的數學運算符(+, -, *, /, %, <<,>>, &, and |)在展開前會將兩個操做數放入 NUMERIC 儲存類。即便這個過程是有損和不可逆轉的。一個 NULL 操做數在數學運算符上產生一個NULL 結果。在數算運算符上的操做數不被視爲數字,NULL並不會被轉爲00.0

5.0 排序, 分組組合查詢

當查詢結果使用 ORDER BY 子句排序時, 存儲類型的NULL空值是排在第一位的, 其次是INTEGER和散佈在數字順序的REAL數據, 其次是按照覈對序列順序的TEXT, 最後爲memcmp()order BLOB. 排序以前不會出現任何存儲類型轉換.

當使用GROUP BY 子句分組時不一樣類型的值被認爲是不一樣的數據, 除了INTEGERREAL 值若是他們數值相等則被認爲是相同的的數據. 沒有任何親和性適用於GROUPBY 子句結果的任意值.

組合查詢使用 UNION, INTERSECT EXCEPT 在數據之間執行隱式的比較. 沒有任何親和性適用於與UNION,INTERSECT, 或者EXCEPT關聯的隱式比較的運算數 - 數據的比較就像這樣.

6.0 整理序列

SQLite 比較兩個字符串時,它使用一個整理序列或整理函數(一物兩表)來決定當兩個字符串相同時,哪一個字符串值更高。SQLite擁有三個內建整理函數:BINARY,NOCASE, RTRIM

1     BINARY - 使用memcmp() 比較字符串,無視文本編碼。

2     NOCASE - 與二進制比較相同,除了ASCII 26個大寫字母在比較前將會轉爲其小寫形勢。注意,只有ASCII 字符會大小寫轉化。因爲表大小的需求,SQLite並不會嘗試UTF 大小寫轉化。

3     RTRIM - 與二進制比較相同,除了尾部空格符將被忽略。

應用能夠經過 sqlite3_create_collation() 接口註冊額外的整理函數。

6.1 設定SQL中的排列順序

每一個表中的每個列都具備一個相關的排序函數。若是沒有顯式地定義排序函數,那麼,就會缺省使用BINARY做爲排序函數。列定義中的COLLATE子句可爲列定義一個可選的排序函數。

對於二元比較運算符(=, <, >, <=, >=,!=, IS, and IS NOT)來講,斷定到底使用哪一個排序函數的規則按順序以下所列:

1     若是兩個操做數中有任意一個操做數具備使用後綴COLLATE運算符顯式定義的排序函數,那麼就會用該函數進行比較,若是兩個操做數都有的狀況下,優先使用左操做數的排序函數。

2     若是兩個操做數中任意一個操做數是一個列,那麼就會使用該列的排序函數進行比較,但在兩個操做數都是列的狀況下,優先使用左操做數對應的列的排序函數。爲了達到這句話的目的,列名前帶有1個或多個一元運算符"+"的,仍然按原列名處理。

3     其它狀況下,採用BINARY排序函數進行比較。

比較運算中的操做數,若是在它的任何子表達式中使用了後綴COLLATE運算符,就能夠認爲是具備顯式的排序函數(上文中的規則1)。再者,若是在比較表達式中的任何地方使用了COLLATE運算符,那麼該運算符所定義的排序函數就會用於字符串的比較,而不管在表達式中出現了表中的哪一列。若是在比較中的任何地方出現了兩個或多個COLLATE運算符子表達式,不管在表達式中嵌入得多深,也不管表達式是怎麼使用括號的,都會使用出如今最左側的顯式排序函數。

表達式"x BETWEEN y and z"從邏輯上講,同"x>= y AND x <= z"這兩個比較運算徹底等價,在使用排序函數時它們倆要象兩個原本就是獨立的比較運算同樣進行處理。在斷定排列順序時,表達式"xIN (SELECT y ...)"處理方式徹底同表達式"x = y"同樣,形如"x IN (y, z, ...)"的表達式,排列順序徹底同X的排列順序同樣。

做爲 SELECT語句的一個部分,ORDER BY子句中排序條件也能夠經過使用COLLATE運算符設定排列順序,若是設定了排序時就要按照設定的排序函數進行排序。不然,若是ORDERBY子句使用的排序表達式是一個列,那麼該列的排列順序就用於斷定排列順序。若是該排序表達式不是列而且也無COLLATE子句,就會使用BINARY排列順序。

6.2 整理序列示例

下面的示例將識別整理序列,決定 SQL 語句的文本比較結果。注意,在文本比較時,若是是數字,二進制或Null值,整理序列可能並無被使用。

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

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 */

);

          /*  x  a   b   c    d */

INSERT INTO  t1 VALUES(1,'abc','abc', 'abc ','abc');

INSERT INTO  t1 VALUES(2,'abc','abc', 'abc', 'ABC');

INSERT INTO  t1 VALUES(3,'abc','abc', 'abc ', 'Abc');

INSERT INTO  t1 VALUES(4,'abc','abc ','ABC', 'abc');

  

/*  a=b 的文本比較表現爲使用 BINARY(二進制)整理序列。 */

SELECT x FROM  t1 WHERE a = b ORDER BY  x;

--結果 1 2 3

  

/*  a=b 的文本比較表現爲使用 RTRIM 整理序列。 */

SELECT x FROM  t1 WHERE a = b COLLATE RTRIM ORDER  BY x;

--結果 1 2 3 4

  

/*  d=a 的文本比較表現爲使用 NOCASE 整理序列。 */

SELECT x FROM  t1 WHERE d = a ORDER BY  x;

--結果 1 2 3 4

  

/*  a=d 的文本比較表現爲使用 BINARY(二進制)整理序列。 */

SELECT x FROM  t1 WHERE a = d ORDER BY  x;

--結果 1 4

  

/* 'abc'=c 的文本比較表現爲使用 RTRIM (二進制)整理序列。 */

SELECT x FROM  t1 WHERE 'abc'  = c ORDER BY x;

--結果 1 2 3

  

/* c='abc' 的文本比較表現爲使用 RTRIM 整理序列。 */

SELECT x FROM  t1 WHERE c = 'abc' ORDER  BY x;

--結果 1 2 3

  

/* 分組表現爲使用 NOCASE 整理序列(值'abc''ABC' 'Abc'

** 被分爲同一組)。*/

SELECT count(*)  FROM t1 GROUP  BY d ORDER  BY 1;

--結果 4

  

/* 分組表現爲使用 BINARY整理序列(值'abc''ABC' 'Abc'

** 被分爲不一樣的組)。*/

SELECT count(*)  FROM t1 GROUP  BY (d || '')  ORDER BY  1;

--結果 1 1 2

  

/* c排序表現爲使用 RTRIM 整理序列。*/(譯註:sorting or column  c 疑爲 sorting of...誤寫)

SELECT x FROM  t1 ORDER BY c, x;

--結果 4 1 2 3

  

/*  (c||'')排序表現爲使用 BINARY整理序列。*/

SELECT x FROM  t1 ORDER BY (c||''), x;

--結果 4 2 3 1

  

/* c排序表現爲使用 NOCASE 整理序列。*/

SELECT x FROM  t1 ORDER BY c COLLATE  NOCASE, x;

--結果 2 4 3 1

相關文章
相關標籤/搜索