1. 程式人生 > >WILLIAM-HUAN 個人技術部落格

WILLIAM-HUAN 個人技術部落格

一、儲存種類和資料型別:

    SQLite將資料值的儲存劃分為以下幾種儲存型別:
     NULL: 表示該值為NULL值。
     INTEGER: 無符號整型值。
     REAL: 浮點值。
     TEXT: 文字字串,儲存使用的編碼方式為UTF-8、UTF-16BE、UTF-16LE。
     BLOB: 儲存Blob資料,該型別資料和輸入資料完全相同。
    由於SQLite採用的是動態資料型別,而其他傳統的關係型資料庫使用的是靜態資料型別,即欄位可以儲存的資料型別是在表宣告時即以確定的,因此它們之間 在資料儲存方面還是存在著很大的差異。在SQLite中,儲存分類和資料型別也有一定的差別,如INTEGER儲存類別可以包含6種不同長度的 Integer資料型別,然而這些INTEGER資料一旦被讀入到記憶體後,SQLite會將其全部視為佔用8個位元組無符號整型。因此對於SQLite而 言,即使在表宣告中明確了欄位型別,我們仍然可以在該欄位中儲存其它型別的資料。然而需要特別說明的是,儘管SQLite為我們提供了這種方便,但是一旦 考慮到資料庫平臺的可移植性問題,我們在實際的開發中還是應該儘可能的保證資料型別的儲存和宣告的一致性。除非你有極為充分的理由,同時又不再考慮資料庫 平臺的移植問題,在此種情況下確實可以使用SQLite提供的此種特徵。
   1. 布林資料型別:


    SQLite並沒有提供專門的布林儲存型別,取而代之的是儲存整型1表示true,0表示false。

   2. 日期和時間資料型別:
    和布林型別一樣,SQLite也同樣沒有提供專門的日期時間儲存型別,而是以TEXT、REAL和INTEGER型別分別不同的格式表示該型別,如:
    TEXT: "YYYY-MM-DD HH:MM:SS.SSS"
    REAL: 以Julian日期格式儲存
    INTEGER: 以Unix時間形式儲存資料值,即從1970-01-01 00:00:00到當前時間所流經的秒數。

二、型別親緣性:

    為了最大化SQLite和其它資料庫引擎之間的資料型別相容性,SQLite提出了"型別親緣性(Type Affinity)"的概念。我們可以這樣理解"型別親緣性 ",在表字段被宣告之後,SQLite都會根據該欄位宣告時的型別為其選擇一種親緣型別,當資料插入時,該欄位的資料將會優先採用親緣型別作為該值的儲存 方式,除非親緣型別不匹配或無法轉換當前資料到該親緣型別,這樣SQLite才會考慮其它更適合該值的型別儲存該值。SQLite目前的版本支援以下五種 親緣型別:

親緣型別 描述  
TEXT 數值型資料在被插入之前,需要先被轉換為文字格式,之後再插入到目標欄位中。
NUMERIC 當文字資料被插入到親緣性為NUMERIC的 欄位中時,如果轉換操作不會導致資料資訊丟失以及完全可逆,那麼SQLite就會將該文字資料轉換為INTEGER或REAL型別的資料,如果轉換失 敗,SQLite仍會以TEXT方式儲存該資料。對於NULL或BLOB型別的新資料,SQLite將不做任何轉換,直接以NULL或BLOB的方式儲存 該資料。需要額外說明的是,對於浮點格式的常量文字,如"30000.0",如果該值可以轉換為INTEGER同時又不會丟失數值資訊,那麼SQLite 就會將其轉換為INTEGER的儲存方式。
INTEGER 對於親緣型別為INTEGER的欄位,其規則等同於NUMERIC,唯一差別是在執行CAST表示式時。
REAL 其規則基本等同於NUMERIC,唯一的差別是不會將"30000.0"這樣的文字資料轉換為INTEGER儲存方式。
NONE 不做任何的轉換,直接以該資料所屬的資料型別進行儲存。  

   1. 決定欄位親緣性的規則:
    欄位的親緣性是根據該欄位在宣告時被定義的型別來決定的,具體的規則可以參照以下列表。需要注意的是以下列表的順序,即如果某一欄位型別同時符合兩種親緣性,那麼排在前面的規則將先產生作用。
    1). 如果型別字串中包含"INT",那麼該欄位的親緣型別是INTEGER。
    2). 如果型別字串中包含"CHAR"、"CLOB"或"TEXT",那麼該欄位的親緣型別是TEXT,如VARCHAR。
    3). 如果型別字串中包含"BLOB",那麼該欄位的親緣型別是NONE。
    4). 如果型別字串中包含"REAL"、"FLOA"或"DOUB",那麼該欄位的親緣型別是REAL。
    5). 其餘情況下,欄位的親緣型別為NUMERIC。

    2. 具體示例:

宣告型別 親緣型別 應用規則
INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED BIG INT
INT2
INT8
INTEGER 1
CHARACTER(20)
VARCHAR(255)
VARYING CHARACTER(255)
NCHAR(55)
NATIVE CHARACTER(70)
NVARCHAR(100)
TEXT
CLOB
TEXT 2
BLOB NONE 3
REAL
DOUBLE
DOUBLE PRECISION
FLOAT
REAL 4
NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIME
NUMERIC 5

    注:在SQLite中,型別VARCHAR(255)的長度資訊255沒有任何實際意義,僅僅是為了保證與其它資料庫的宣告一致性。

三、比較表示式:

    在SQLite3中支援的比較表示式有:"=", "==", "<", "<=", ">", ">=", "!=", "<>", "IN", "NOT IN", "BETWEEN", "IS" and "IS NOT"。
    資料的比較結果主要依賴於運算元的儲存方式,其規則為:
    1). 儲存方式為NULL的數值小於其它儲存型別的值。
    2). 儲存方式為INTEGER和REAL的數值小於TEXT或BLOB型別的值,如果同為INTEGER或REAL,則基於數值規則進行比較。
    3). 儲存方式為TEXT的數值小於BLOB型別的值,如果同為TEXT,則基於文字規則(ASCII值)進行比較。
    4). 如果是兩個BLOB型別的數值進行比較,其結果為C執行時函式memcmp()的結果。

四、操作符:

    所有的數學操作符(+, -, *, /, %, <<, >>, &, and |)在執行之前都會先將運算元轉換為NUMERIC儲存型別,即使在轉換過程中可能會造成資料資訊的丟失。此外,如果其中一個運算元為NULL,那麼它們 的結果亦為NULL。在數學操作符中,如果其中一個運算元看上去並不像數值型別,那麼它們結果為0或0.0。

-------

上面的這一小段來自:http://www.cnblogs.com/stephen-liu74/archive/2012/02/22/2325258.html,其實這裡也有一份,不過這一份嘛 ,就整理的不太好了。所以我扔到code框裡。。其實以前有一份pdf的,但一下子找不到了。而且。。。mac下看chm和pdf都不太爽。。

  1. NULL  
  2. INTEGER  
  3. REAL  
  4. TEXT  
  5. BLOB  
  6. 但實際上,sqlite3也接受如下的資料型別:  
  7. smallint 16 位元的整數。  
  8. interger 32 位元的整數。  
  9. decimal(p,s) p 精確值和 s 大小的十進位整數,精確值p是指全部有幾個數(digits)大小值,s是指小數點後有幾位數。如果沒有特別指定,則系統會設為 p=5s=0 。  
  10. float   32位元的實數。  
  11. double   64位元的實數。  
  12. char(n)   n 長度的字串,n不能超過 254。  
  13. varchar(n) 長度不固定且其最大長度為 n 的字串,n不能超過 4000。  
  14. graphic(n) 和 char(n) 一樣,不過其單位是兩個字元 double-bytes, n不能超過127。這個形態是為了支援兩個字元長度的字型,例如中文字。  
  15. vargraphic(n) 可變長度且其最大長度為 n 的雙字元字串,n不能超過 2000  
  16. date   包含了 年份、月份、日期。  
  17. time   包含了 小時、分鐘、秒。  
  18. timestamp 包含了 年、月、日、時、分、秒、千分之一秒。  
  19. 1.儲存類別  
  20. 第二版把所有列的值都儲存成ASCII文字格式。第三版則可以把資料儲存成整數和實數,還可以儲存BLOB資料.  
  21. Each value stored in an SQLite資料庫中儲存的每個值都有一個屬性,都屬於下面所列類中的一種,(被資料庫引擎所控制)  
  22. 空.這個值為空值  
  23. 整數.值被標識為整數,依據值的大小可以依次被儲存為1,2,3,4,5,6,7,8.  
  24. 實數. 所有值都是浮動的數值,被儲存為8位元組的IEEE浮動標記序號.  
  25. 文字. 值為文字字串,使用資料庫編碼儲存(TUTF-8, UTF-16BE or UTF-16-LE).  
  26. BLOB. 值是BLOB資料,如何輸入就如何儲存,不改變格式.  
  27. 像SQLite2.0版一樣,在3.0版中,除了INTEGER PRIMARY KEY,資料庫中的任何列都可以儲存任何型別的資料.這一規則也有例外,在下面的"嚴格相似模式"中將描述.  
  28. 輸入SQLite的所有值,不管它是嵌入 SQL語句中的文字還是提前編譯好的繫結在SQL語句中的值,在SQL語句執行前都被儲存為一個類.在下面所描述的情況下,資料庫引擎將在執行時檢查並把值在數字儲存類(整數和實數)和文字類間轉換.  
  29. 儲存的類別最初被分類為如下:  
  30. 具體的值比如SQL語句部分的帶雙引號或單引號的文字被定義為文字,如果文字沒帶引號並沒有小數點或指數則被定義為整數,如果文字沒帶引號但有小數點或指數則被定義為實數,如果值是空則被定義為空值.BLOB資料使用符號X'ABCD'來標識.  
  31. Values supplied using the 被輸入的值使用sqlite3_bind_* APIs的被分類一個儲存等級,這等級是和原來的類基本相一致的. (比如sqlite3_bind_blob()繫結一個BLOB的值).  
  32. 值的分類是SQL分等級操作的結果,決定於最遠的操作表示式.使用者定義的功能也許會把值返回任意的類.在編譯的時候來確定表示式的儲存類基本是不可能的.  
  33. 2. 列之間的親和性  
  34. 在SQLite3.0版中,值被定義為什麼型別只和值自身有關,和列沒有關係,和變數也沒有關係. (這有時被稱作 弱型別.)所有其它的我們所使用的資料庫引擎都受靜態型別系統的限制,其中的所有值的類是由其所屬列的屬性決定的,而和值無關.  
  35. 為了最大限度的增加SQLite資料庫和其他資料庫的相容性,SQLite支援列的"型別親和性". 列的親和性是為該列所儲存的資料建議一個型別.我們要注意是建議而不是強迫.在理論上來講,任何列依然是可以儲存任何型別的資料的. 只是針對某些列,如果給建議型別的話,資料庫將按所建議的型別儲存.這個被優先使用的資料型別則被稱為"親和型別".  
  36. 在SQLite3.0版中,資料庫中的每一列都被定義為以下親和型別中的一種:  
  37. 文字  
  38. 數字的  
  39. 整數  
  40. 無  
  41. 一個具有型別親和性的列按照無型別,文字,或BLOB儲存所有的資料.如果數字資料被插入一個具有文字型別親和性的列,在儲存之前數字將被轉換成文字.  
  42. 一個具有數字型別親和性的列也許使用所有的五個儲存型別儲存值.當文字資料被插入一個數字列時,在儲存之前,資料庫將嘗試著把文字轉換成整數或實數.如果能成功轉換的話,值將按證書活實數的型別被儲存. 如果不能 成功轉換的話,值則只能按文字型別儲存了,而不會被轉換成無型別或BLOB型別來儲存.  
  43. 一個具有整數親和力的列在轉換方面和具有數字親和力的列是一樣的,但也有些區別 ,比如沒有浮動量的實值(文字值轉換的值)被插入具有整數親和力的列時,它將被轉換成整數並按整數型別儲存.  
  44. 一個具有無型別親和力的列不會優先選擇使用哪個型別.在資料被輸入前它不會強迫資料轉換型別.  
  45. 2.1 列的親和性的決定  
  46. 一個列的親和型別是由該列所宣稱的型別決定的.遵守以下規則:  
  47. 如果資料型別包括字串"INT"那麼它被定義成具有整數親和性.  
  48. 如果列中的資料型別包括以下任何的字串 "CHAR", "CLOB", or "TEXT" 那麼這個列則具有文字親和性.要注意VARCHAR型別包括字串"CHAR"因此也具有文字型別親和性.  
  49. 如果一個列的資料型別包括字串"BLOB"或者如果資料型別被具體化了,那麼這個列具有無型別親和性.  
  50. 否則就具有數字型別親和性.  
  51. 如果表格使用If "CREATE TABLE AS SELECT..."語句生成的,那麼所有的列則都沒有具體的資料型別,則沒有型別親和性.  
  52. 2.2 列的親和性的例子  
  53. CREATE TABLE t1(  
  54.     t TEXT,  
  55.     nu NUMERIC,  
  56.     i INTEGER,  
  57.     no BLOB  
  58. );  
  59. -- Storage classes for the following row:  
  60. -- TEXT, REAL, INTEGER, TEXT  
  61. INSERT INTO t1 VALUES('500.0', '500.0', '500.0', '500.0');  
  62. -- Storage classes for the following row:  
  63. -- TEXT, REAL, INTEGER, REAL  
  64. INSERT INTO t1 VALUES(500.0, 500.0, 500.0, 500.0);  
  65. 3.比較表示式  
  66. 像SQLite2.0版一樣,3.0版的一個特性是二進位制比較符'=', '<', '<=', '>=' and '!=',一個操作'IN'可以測試固定的成員資格, 三重的比較操作符'BETWEEN'.  
  67. 比較的結果決定於被比較的兩個值的儲存型別。遵循以下規則:  
  68. 一個具有空儲存型別的值被認為小於任何值(包括另外一個具有空儲存型別的值)。  
  69. 一個整數值或實數值小於任何文字值和BLOB值。 當一個整數或實數和另一個整數或實數相比較的時候,則按照實際數值來比較。  
  70. 一個文字值小於BLOB值。當兩個文字值相比較的時候,則用C語言類庫中的memcmp()函式來比較。然而,有時候也不是這樣的,比如在下面所描述的“使用者定義的整理順序”情況下。  
  71. 當兩個BLOB文字被比較的時候,結果決定於memcmp()函式。  
  72. 在開始比較前,SQLite嘗試著把值在數字儲存級(整數和實數)和文字之間相互轉換。下面列舉了關於如何比較二進位制值的例子。在著重號below中使用的表示式可以表示SQL標量表達式或是文字但不是一個列值。  
  73. 當一個列值被比擬為表示式結果的時候,在比較開始前,列的親和性將被應用在表達結果中。  
  74. 當兩個列值比較的時候,如果一個列有整數或數字親和性的時候,而另外一列卻沒有,那麼數字親和性適用於從非數字列提取的任何具有文字儲存型別的值. P>
  75. 當比較兩個表示式的結果時,不發生任何轉換,直接比較結果.如果一個字串和一個數字比較, 數字總是小於字串.  
  76. 在SQLite中, 表示式"a BETWEEN b AND c"等於表示式 "a >= b AND a <= c",在比較表示式時,a可以是具有任何親和性.  
  77. 表示式 "a IN (SELECT b ....)" 在比較時遵循上面所提到的三條規則,是二進位制比較.(例如, 在一個相似的樣式 "a = b"). 例如,如果'b'是一個列值, 'a' 是一個表示式,那麼,在開始比較前,'b'的親和性就被轉換為'a'的親和性了.  
  78. SQLite把表示式 "a IN (x, y, z)" 和 "a = z OR a = y OR a = z"視為相等.  
  79. 3.1 比較例子  
  80. CREATE TABLE t1(  
  81.     a TEXT,  
  82.     b NUMERIC,  
  83.     c BLOB  
  84. );  
  85. -- Storage classes for the following row:  
  86. -- TEXT, REAL, TEXT  
  87. INSERT INTO t1 VALUES('500', '500', '500');  
  88. -- 60 and 40 are converted to '60' and '40' and values are compared as TEXT.  
  89. SELECT a <60, a <40 FROM t1;  
  90. 1|0  
  91. -- Comparisons are numeric. No conversions are required.  
  92. SELECT b <60, b <600 FROM t1;  
  93. 0|1  
  94. -- Both 60 and 600 (storage class NUMERIC) are less than '500'  
  95. -- (storage class TEXT).  
  96. SELECT c <60, c <600 FROM t1;  
  97. 0|0  
  98. 4. 運算子  
  99. 所有的數學運算子(所有的運算子而不是連鎖作用標記符"||")運算物件首先具有數字親和性, 如果一個或是兩個都不能被轉換為數字那麼操作的結果將是空值。  
  100. 對於連線作用操作符,所有操作符將首先具有文字親和性。如果其中任何一個操作符不能被轉換為文字(因為它是空值或是BLOB)連線作用操作符將是空值。  
  101. 5. 分類,排序,混合挑選  
  102. 當用子句ORDER挑選值時,空值首先被挑選出來, 然後是整數和實數按順序被挑選出來, 然後是文字值按memcmp()順序被挑選出來, 最後是BLOB值按memcmp()順序被挑選出來.在挑選之前, 沒有儲存型別的值都被轉換了.  
  103. When grouping values with the 當用GROUP BY子句給值分組時,具有不同儲存型別的值被認為是不同的, 但也有例外, 比如,一個整數值和一個實數值從數字角度來說是相等的,那麼它們則是相等的.用GROUP by 子句比較完後,值不具有任何親和性.  
  104. 混合挑選操作符UNION, INTERSECT and EXCEPT 在值之間實行絕對的比較,同樣的親和性將被應用於所有的值,這些值將被儲存在一個單獨的具有混合SELECT的結果組的列中. 被賦予的親和性是該列的親和性,這個親和性是由剩下的大部分的混合SELECTS返回的,這些混合SELECTS在那個位置上有列值(而不是其它型別的表示式). 如果一個給定的混合SELECT列沒有SELECTS的量, 那麼在比較前,該列的值將不具有任何親和性.  
  105. 6. 其它親和性模式  
  106. 以上的部分所描述的都是資料庫引擎在正常親和性模式下所進行的操作, SQLite將描述其它兩種親和性模式,如下:  
  107. 嚴格親和性模式.在這種模式下,如果需要值之間相互轉換資料儲存型別的話,資料庫引擎將傳送錯誤報告,當前語句也將會重新執行.  
  108. 無親和性模式.在這種模式下,值的資料儲存型別不發生轉換.具有不同儲存型別的值之間不能比較,但整數和實數之間可以比較.  
  109. 7.使用者定義的校對順序  
  110. By default, when 當SQLite比較兩個文字值的時候,通過系統設定,不管字串的編碼是什麼,用memcmp()來比較. SQLite第三版允許使用者提供任意的函式來代替memcmp(),也就是使用者定義的比較順序.  
  111. 除了系統預設的BINARY比較順序,它是用memcmp()函式比較,SQLite還包含了兩個額外的內建比較順序函式, NOCASE和REVERSE:  
  112. BINARY -使用memcmp()比較字串資料, 不考慮文字編碼.  
  113. REVERSE -用倒序比較二進位制文字.  
  114. NOCASE - 和二進位制一樣,但在比較之前,26位的大寫字母盤要被摺合成相應的小寫字母盤.  
  115. 7.1 分配比較順序  
  116. 每個表格中的每個列都有一個預設的比較型別.如果一個比較型別不是二進位制所要求的,比較的子句將被具體化為 列的定義 來定義該列.  
  117. 當用SQLite比較兩個文字值時,比較順序將按照以下的規則來決定比較的結果.文件的第三部分和第五部分描述在何種場合下發生這種比較.  
  118. 對於二進位制比較符(=, <><= and >=),如果每個運算元是一列的話,那麼該列的預設比較型別決定於所使用的比較順序. 如果兩個運算元都是列的話,那麼左邊的運算元的比較型別決定了所要使用的比較順序.如果兩個運算元都不是一列,將使用二進位制來比較.  
  119. 表示式"x BETWEEN y and z"和 "x >= y AND x <= z"是相同的. 表示式"x IN (SELECT y ...)" 和表示式 "xx = y" 使用同樣的方法來操作,這是為了決定所要使用的比較順序.如果X是一列或者二進位制的,則"x IN (y, z ...)" 形式的表示式所使用的比較順序是X的預設的比較型別.  
  120. ORDER BY clause that is part of a SELECT statement may be assigned a collation sequence to be used for the sort operation explicitly. In this case the explicit collation sequence is always used. Otherwise, if the expression sorted by an ORDER BY clause is a column, then the default collation type of the column is used to determine sort order. If the expression is not a column, then the BINARY collation sequence is used.  
  121. 7.2 比較順序的例子  
  122. 下面的例子介紹了The examples below identify the collation sequences that would be used to determine the results of text comparisons that may be performed by various SQL statements. Note that a text comparison may not be required, and no collation sequence used, in the case of numeric, blob or NULL values.  
  123. CREATE TABLE t1(  
  124.     a,                 -- default collation type BINARY  
  125.     b COLLATE BINARY, -- default collation type BINARY  
  126.     c COLLATE REVERSE, -- default collation type REVERSE  
  127.     d COLLATE NOCASE   -- default collation type NOCASE  
  128. );  
  129. -- Text comparison is performed using the BINARY collation sequence.  
  130. SELECT (a = b) FROM t1;  
  131. -- Text comparison is performed using the NOCASE collation sequence.  
  132. SELECT (d = a) FROM t1;  
  133. -- Text comparison is performed using the BINARY collation sequence.  
  134. SELECT (a = d) FROM t1;  
  135. -- Text comparison is performed using the REVERSE collation sequence.  
  136. SELECT ('abc' = c) FROM t1;  
  137. -- Text comparison is performed using the REVERSE collation sequence.  
  138. SELECT (c = 'abc') FROM t1;  
  139. -- Grouping is performed using the NOCASE collation sequence (i.e. values  
  140. -- 'abc' and 'ABC' are placed in the same group).  
  141. SELECT count(*) GROUP BY d FROM t1;  
  142. -- Grouping is performed using the BINARY collation sequence.  
  143. SELECT count(*) GROUP BY (d || '') FROM t1;  
  144. -- Sorting is performed using the REVERSE collation sequence.  
  145. SELECT * FROM t1 ORDER BY c;  
  146. -- Sorting is performed using the BINARY collation sequence.  
  147. SELECT * FROM t1 ORDER BY (c || '');  
  148. -- Sorting is performed using the NOCASE collation sequence.  
  149. SELECT * FROM t1 ORDER BY c COLLATE NOCASE;  

如前文所述,SQLite在處理資料型別時與其它的資料庫不同。區別在於它所支援的型別以及這些型別是如何儲存、比較、強化(enforc)和指派(assign)。下面各節介紹SQLite處理資料型別的獨特方法和它與域完整性的關係。

對於資料型別,SQLite的域完整性被稱為域親和性(affinity)更合適。在SQLite中,它被稱為型別親和性(type affinity)。為了理解型別親和性,你必須先要理解儲存類和弱型別(manifesttyping)。

SQLite有5個原始的資料型別,被稱為儲存類。儲存類這個詞表明瞭一個值在磁碟上儲存的格式,其實就是型別或資料型別的同義詞。這5個儲存類在表4-6中描述。

表 4-6 SQLite儲存類

 

名稱

 
 

說明

 
 

INTEGER

 
 

整數值是全數字(包括正和負)。整數可以是1, 2, 3, 4, 6或 8位元組。整數的最大範圍(8 bytes)是{-9223372036854775808, 0, +9223372036854775807}。SQLite根據數字的值自動控制整數所佔的位元組數。

 

空注:參可變長整數的概念。

 
 

REAL

 
 

實數是10進位制的數值。SQLite使用8位元組的符點數來儲存實數。

 
 

TEXT

 
 

文字(TEXT)是字元資料。SQLite支援幾種字元編碼,包括UTF-8和UTF-16。字串的大小沒有限制。

 
 

BLOB

 
 

二進位制大物件(BLOB)是任意型別的資料。BLOB的大小沒有限制。

 
 

NULL

 
 

NULL表示沒有值。SQLite具有對NULL的完全支援。

 

SQLite通過值的表示法來判斷其型別,下面就是SQLite的推理方法:

l  SQL語句中用單引號或雙引號括起來的文字被指派為TEXT。

l  如果文字是未用引號括起來的資料,並且沒有小數點和指數,被指派為INTEGER。

l  如果文字是未用引號括起來的資料,並且帶有小數點或指數,被指派為REAL。

l  用NULL說明的值被指派為NULL儲存類。

l  如果一個值的格式為X'ABCD',其中ABCD為16進位制數字,則該值被指派為BLOB。X字首大小寫皆可。

SQL函式typeof()根據值的表示法返回其儲存類。使用這個函式,下面SQL語句返回的結果為:

sqlite> select typeof(3.14),typeof('3.14'), typeof(314), typeof(x'3142'), typeof(NULL);

typeof(3.14)   typeof('3.14')  typeof(314)    typeof(x'3142')       typeof(NULL)

real                text                integer           blob                      null

SQLite單獨的一個欄位可能包含不同儲存類的值。請看下面的示例:

sqlite> DROP TABLE domain;

sqlite> CREATE TABLE domain(x);

sqlite> INSERT INTO domain VALUES(3.142);

sqlite> INSERT INTO domain VALUES('3.142');

sqlite> INSERT INTO domain VALUES(3142);

sqlite> INSERT INTO domain VALUES(x'3142');

sqlite> INSERT INTO domain VALUES(NULL);

sqlite> SELECT ROWID, x, typeof(x) FROMdomain;

返回結果為:

rowid      x            typeof(x)

1            3.142      real

2            3.142      text

3            3142     integer

4            1B        blob

5            NULL    null

這帶來一些問題。這種欄位中的值如何儲存和比較?如何對一個包含了INTEGER、REAL、TEXT、BLOB和NULL值的欄位排序?一個整數和一個BLOB如何比較?哪個更大?它們能相等嗎?

答案是:具有不同儲存類的值可以儲存在同一個欄位中。可以被排序,因為這些值可以相互比較。有完善定義的規則來做這件事。不同儲存類的值可以通過它們各自類的“類值”進行排序,定義如下:

1. NULL儲存類具有最低的類值。一個具有NULL儲存類的值比所有其它值都小(包括其它具有NULL儲存類的值)。在NULL值之間,沒有特別的可排序值。

2. INTEGER或REAL儲存類值高於NULL,它們的類值相等。INTEGER值和REAL值通過其數值進行比較。

3. TEXT儲存類的值比INTEGER和REAL高。數值永遠比字串的值低。當兩個TEXT值進行比較時,其值大小由“排序法”決定。

4. BLOB儲存類具有最高的類值。具有BLOB類的值大於其它所有類的值。BLOB值之間在比較時使用C函式memcmp()。

所以,當SQLite對一個欄位進行排序時,首先按儲存類排序,然後再進行類內的排序 (NULL類內部各值不必排序) 。下面的SQL說明了儲存類值的不同:

sqlite> SELECT 3 < 3.142, 3.142 <'3.142', '3.142' < x'3000', x'3000' < x'3001';

返回:

3 < 3.142              3.142 < '3.142'              '3.142'< x'3000'     x'3000' < x'3001'

1                   1                          1                          1

弱型別(manifest typing)

SQLite使用弱型別。

看下面的表:

CREATE TABLE foo( x integer,

    y text, z real );

向該表插入一條記錄:

INSERT INTO foo VALUES ('1', '1', '1');

當SQLite建立這條記錄時,x、y和z這3個欄位中儲存的是什麼型別呢?答案是INTEGER, TEXT和REAL。

再看下面例子:

CREATE TABLE foo(x, y, z);

現在執行同樣的插入語句:

INSERT INTO foo VALUES ('1', '1', '1');

現在,x、y和z中儲存的是什麼型別呢?答案是TEXT、TEXT和TEXT。

那麼,是否SQLite的欄位型別預設為TEXT呢?再看,還是第2個表,執行如下插入語句:

INSERT INTO foo VALUES (1, 1.0, x'10');

現在,x、y和z中儲存的是什麼型別呢?答案是INTEGER、REAL和BLOB。

如果你願意,可以為SQLite的欄位定義型別,這看起來跟其它資料庫一樣。但這不是必須的,你可以儘管違反型別定義。這是因為在任何情況下,SQLite都可以接受一個值並推斷它的型別。

總之,SQLite的弱型別可表示為:1)欄位可以有型別,2)型別可以通過值來推斷。型別親和性介紹這兩個規定如何相互關聯。所謂型別親和性就是在強型別(strict typing)和動態型別(dynamic typing)之間的平衡藝術。

型別親和性(Type Affinity)

在SQLite中,欄位沒有型別或域。當給一個欄位聲明瞭型別,該欄位實際上僅僅具有了該型別的新和性。宣告型別和型別親和性是兩回事。型別親和性預定 SQLite用什麼儲存類在欄位中儲存值。在儲存一個給定的值時到底SQLite會在該欄位中用什麼儲存類決定於值的儲存類和欄位親和性的結合。我們先來介紹一下欄位如何獲得它的親和性。

欄位型別和親和性

首先,每個欄位都具有一種親和性。共有四種親和性:NUMERIC、INTEGER、TEXT和NONE。一個欄位的親和性由它預宣告的型別決定。所以,當你為欄位聲明瞭型別,從根本上說是為欄位指定了親和性。SQLite按下面的規則為欄位指派親和性:

l  預設的,一個欄位預設的親和性是NUMERIC。如果一個欄位不是INTEGER、TEXT或NONE的,那它自動地被指派為NUMERIC親和性。

l  如果為欄位宣告的型別中包含了'INT'(無論大小寫),該欄位被指派為INTEGER親和性。

l  如果為欄位宣告的型別中包含了'CHAR'、'CLOB'或'TEXT'(無論大小寫),該欄位被指派為TEXT親和性。如'VARCHAR'包含了'CHAR',所以被指派為TEXT親和性。

l  如果為欄位宣告的型別中包含了'BLOB'(無論大小寫),或者沒有為該欄位宣告型別,該欄位被指派為NONE親和性。

注意:如果沒有為欄位宣告型別,該欄位的親和性為NONE,在這種情況下,所有的值都將以它們本身的(或從它們的表示法中推斷的)儲存類儲存。如果你暫時還不確定要往一個欄位裡放什麼內容,或準備將來修改,用NONE親和性是一個好的選擇。但SQLite預設的親和性是NUMERIC。例如,如果為一定欄位聲明瞭型別JUJYFRUIT,該欄位的親和性不是NONE,因為SQLite不認識這種型別,會給它指派預設的NUMERIC親和性。所以,與其用一個不認識的型別最終得到NUMERIC親和性,還不如不為它指定型別,從而使它得到NONE親和性。

親和性和儲存

親和性對值如何儲存到欄位有影響,規則如下:

l  一個NUMERIC欄位可能包括所有5種儲存類。一個NUMERIC欄位具有數字儲存類的偏好(INTEGER和REAL)。當一個TEXT值被插入到一個NUMERIC欄位,將會試圖將其轉化為INTEGER儲存類;如果轉化失敗,將會試圖將其轉化為REAL儲存類;如果還是失敗,將會用TEXT儲存類來儲存。

l  一個INTEGER欄位的處理很像NUMERIC欄位。一個INTEGER欄位會將REAL值按REAL儲存類儲存。也就是說,如果這個REAL值沒有小數部分,就會被轉化為INTEGER儲存類。INTEGER欄位將會試著將TEXT值按REAL儲存;如果轉化失敗,將會試圖將其轉化為INTEGER儲存類;如果還是失敗,將會用TEXT儲存類來儲存。

l  一個TEXT欄位將會把所有的INTEGER或REAL值轉化為TEXT。

l  一個NONE欄位不試圖做任何型別轉化。所有值按它們本身的儲存類儲存。

l  沒有欄位試圖向NULL或BLOB值轉化——如無論用什麼親和性。NULL和BLOB值永遠都按本來的方式儲存在所有欄位。

這些規則初看起來比較複雜,但總的設計目標很簡單,就是:如果你需要,SQLite會盡量模仿其它的關係型資料庫。也就是說,如果你將SQLite看成是一個傳統資料庫,型別親和性將會按你的期望來儲存值。如果你聲明瞭一個INTEGER欄位,並向裡面放一個整數,就會按整數來儲存。如果你聲明瞭一個具有 TEXT, CHAR或VARCHAR型別的欄位並向裡放一個整數,整數將會轉化為TEXT。可是,如果你不遵守這些規定,SQLite也會找到辦法來儲存你的值。

親和性的執行

讓我們看一些例子來了解親和性是如何工作的:

sqlite> CREATE TABLE domain(i int, nnumeric, t text, b blob);

sqlite> INSERT INTO domain VALUES(3.142,3.142,3.142,3.142);

sqlite> INSERT INTO domain VALUES('3.142','3.142','3.142','3.142');

sqlite> INSERT INTO domain VALUES(3142,3142,3142,3142);

sqlite> INSERT INTO domain VALUES(x'3142',x'3142',x'3142',x'3142');

sqlite> INSERT INTO domain VALUES(null,null,null,null);

sqlite> SELECT ROWID,typeof(i),typeof(n),typeof(t),typeof(b)FROM domain;

返回:

rowid      typeof(i)  typeof(n) typeof(t)  typeof(b)

1            real         real         text         real

2            real         real         text         text

3            integer    integer    text         integer

4            blob        blob        blob        blob

5            null         null         null         null

下面的SQL說明儲存類的排序情況:

sqlite> SELECT ROWID, b, typeof(b) FROMdomain ORDER BY b;

返回:

rowid b typeof(b)

5 NULL null

1 3.142 real

3 3142 integer

2 3.142 text

4 1B blob

sqlite> SELECT ROWID, b, typeof(b),b<1000 FROM domain ORDER BY b;

返回:

rowid b typeof(b) b<1000

NULL null NULL

1 3.142 real 1

3 3142 integer 1

2 3.142 text 0

4 1B blob 0

儲存類和型別轉換

關於儲存類,需要關注的另一件事是:儲存類有時會影響到值如何進行比較。特別是SQLite有時在進行比較之前,會將值在數字儲存類(INTEGER和REAL)和TEXT之間進行轉換。為進行二進位制的比較,遵循如下規則:

l  當一個欄位值與一個表示式的結果進行比較,欄位的親和性會在比較之前應用於表示式的結果。

l  當兩個欄位值進行比較,如果一個欄位擁有INTEGER或NUMERIC親和性而另一個沒有,NUMERIC親和性會應用於非NUMERIC欄位的TEXT值。

l  當兩個表示式進行比較,SQLite不做任何轉換。如果兩個表示式有相似的儲存類,則直接按它們的值進行比較;否則按類值進行比較。

請看下面例子:

sqlite> selectROWID,b,typeof(i),i>'2.9' from domain ORDER BY b;

rowid b typeof(i i>'2.9'

5 NULL null NULL

1 3.142 real 1

3 3142 integer 1

2 3.142 real 1

4 1B blob 1

也算是“強型別(STRICT TYPING)”

如果你需要比型別親和性更強的域完整性,可以使用CHECK約束。你可以使用一個單獨的內建函式和一個CHECK約束來實現一個“假的”強型別。

相關推薦

WILLIAM-HUAN 個人技術部落

一、儲存種類和資料型別:     SQLite將資料值的儲存劃分為以下幾種儲存型別:     NULL: 表示該值為NULL值。     INTEGER: 無符號整型值。     REAL: 浮點值。     TEXT: 文字字串,儲存使用的編碼方式為UTF-8、UTF-16BE、UTF-16LE。    

Jekyll + Github Pages構建個人技術部落

寫技術部落格可以積累並且鞏固所學的知識,溫故知新,還能傳播知識,幫助他人解決問題。 前言 搭建專屬於自己的部落格,是每一個碼農都會想要去實現的,以前自己也曾想要搭建,但是總有無從下手的感覺,隨著知識閱歷的提升,知道了一些搭建的方式,時機成熟,

使用GitHub+Hexo+hexo-theme-indigo(主題)搭建自己的個人技術部落

本次搭建實在windows系統下完成: 前提條件:已經下載git、Hexo、node.js等必要的工具環境 第一步:初始化一個本地的Hexo專案 再本地建立一個部落格系統目錄:我建立的是專案根目錄:OyjBlog 再OyjBlog目錄下右鍵開啟Git Bash終端

如何擁有個人的Github技術部落

題圖:87testing.com前不久用wordpress搭建了一個部落格,用起來感覺不是太好用

評判一篇技術部落價值的標準一些個人見解

    1.將複雜的問題簡單化:               勤勞的牛人: 把原本複雜的問題,簡單化,可以得到更多的觀眾關注度,因為只有越簡單的方式解釋越複雜的問題,才能有更多的讀者來去讀且讀懂,如果很多關鍵性問題的研究一筆帶過,且認為顯而易見,那麼說明該論文或者程式解釋得

個人很吊的技術部落

解讀對日軟體外包(2012還在上學時轉載,目前2018年從對日外包離職,說的情況即使現在還是一樣) 一、 前言 外包、軟體外包、對日軟體外包。這些都是什麼?您對它們都有了解麼?您是否正在考慮 去一家外包企業工作?如果大家對外包和軟體外包還不甚瞭解的話可以先找些相關文章參 閱。

這是三篇影響百度17年的技術部落,作者李彥巨集

來源 | DoNews 作者 | 李彥巨集 我與GO.COM 本文寫於2001年2月3日。         雖然早已是預料之中的事,但得知GO.COM關閉的訊息時,還是有些傷感,畢竟我為她和她的前身

基於mkdocs-material搭建個人靜態部落

基於mkdocs-material搭建個人純靜態部落格,沒有php,沒有mysql 如果你只是想安安靜靜的放一些技術文章,釋出到個人站點或github-pages,mkdocs-material很適合你 小慢哥的原創文章,歡迎轉載 本文僅是縮略,筆者已將詳細內容釋出到github上

用碼雲搭建簡單的個人個性部落

很簡單,大概一個小時就可以做好! 先說下原理 碼雲pages是一個靜態網站託管地方,再加上碼雲本來就是個程式碼託管的地方,整合pages後,可以很方便的部署你的程式碼 本文原理:利用 馬克飛象生成部落格的md檔案,利用Hexo把程式碼生成靜態頁面,再一鍵部署到碼雲上,開啟pages後

技術部落的太監

大多數小說,部落格,網站,主頁 最後都逃脫不了一種命運。 寫著寫著就沒有下面了。 這是很多網站的常態,為什麼? 因為一切最終的結局都是歸於平靜。 小說寫的自己編不下去就棄更了, 部落格沒流量沒動力也沒精力維護了, 網站伺服器費用交不起沒備案被404了, 發的說說0贊0評沒朋友純屬自嗨也就放棄了。 所以太監是整

我從寫技術部落中收穫到了什麼?- J_Knight_

我是 J_Knight_,熟悉我的人都應該知道我是一名剛工作滿3年的非科班 iOS 開發者,而且一直堅持寫技術部落格快有2年半的時間了。 其實從去年開始就一直想分享我寫部落格的心得,但是一直也沒有找到合適的契機,剛好在今年年底前達成了掘金粉絲量過萬的小目標,索性就藉著這個機會分享一下我自己關於寫部落格的一些

個人部落搭建(持續更新)

最近的CSDN的部落格閱讀體驗非常的糟糕,恰好自己也一直想搭建一個屬於自己的網站,放下自己的技術心得情感體會,從零開始慢慢搭建專案磨練技術,以後也把自己新習得的技術放在裡面增加自己的學習樂趣。 一,搭建基本的專案模板為專案建立一個資料夾及一些基本檔案,為此用到HTML5 Boilerplate(H

為什麼要寫技術部落

                            前言            

技術部落的無限好處

沒有讀者,寫技術部落格文章感覺不到太多的作用,是浪費時間的事情,是這樣嗎? 不是。 釋出有關軟體技術的部落格將帶來數以千計的美元,儘管沒有人曾讀您的部落格。閒話少敘,首先,讀者可能是寫部落格的目標,但他們實際上是自然的結果。一路上還有很多其他的個人利益,包括更好的工

如何寫一篇好的技術部落

在工作過程中,發現對很多東西都一知半解,不是很透澈,到頭來很容易模糊,如果有一篇好的技術部落格予以總結,一來即使忘記了,回國頭來再看,仍然能夠從自己的思路中恢復;二來總結一下,還會發現一些潛在問題;三來,有利於大家交流技術。很多大公司都有自己的內部技術部落格平臺,寫

在windows下進行 linux 開發 (轉載第七星塵的技術部落

1,介紹Vagrant 我們做web開發的時候經常要安裝各種本地測試環境,比如apache,php,mysql,redis等等。出於個人使用習慣,可能我們還是比較習慣用windows。雖然說在windows下搭建各種開發環境是可行的,各大開發環境都有windows版本。然而在windows下配置有時候會顯

【天山雪的技術部落格】漢家煙塵在東北,漢將辭家破殘賊。男兒本自重橫行,天子非常賜顏色。摐金伐鼓下榆關,旌旆逶迤碣石間。校尉羽書飛瀚海,單于獵火照狼山。山川蕭條極邊土,胡騎憑陵雜風雨。戰士軍前半死生,美人帳下猶歌舞。大漠窮秋塞草腓,孤城落日鬥兵稀。身當恩遇恆輕

漢家煙塵在東北,漢將辭家破殘賊。男兒本自重橫行,天子非常賜顏色。摐金伐鼓下榆關,旌旆逶迤碣石間。校尉羽書飛瀚海,單于獵火照狼山。山川蕭條極邊土,胡騎憑陵雜風雨。戰士軍前半死生,美人帳下猶歌舞。大漠窮秋...

挨踢人,自由軟體開發者Tiandi的技術部落

最近正好有用excel的做些統計的東西,vba的一些用法又從新的review了一下,在此記錄一下: 1. 函式返回 VBA的函式返回通過一個和函式名的相同的變數進行返回,而不用寫return xxx ret = myfunction... 非技術

長期閱讀英文技術部落的好處

最近突然決定要好好學習下自己的英語,所以蒐集下相關文章,摘錄一些準備實踐的觀點: 有人可能覺得學英語聽地道的美式、英式英語是最佳的。但是我覺得非常有必要接觸不同的方言口音。聽一些較歪的口音反而有利於提高我的耳朵對英語聲音的辨別能力。我現在的直接主管是一個法國人,他講話時他把pattern說的像button

黑馬程式設計師技術部落之哲學家吃飯問題

----------- android培訓、java培訓、java學習型技術部落格、期待與您交流! ------------ 哲學家就餐:有五個哲學家繞著圓桌坐,每個哲學家面前有一碗麵,兩人之間有一支筷子,這樣每個哲學家左右各有一支筷子。哲學家有2個狀態,思考或者拿起筷子吃