1. 程式人生 > >sqlite3中的數據類型

sqlite3中的數據類型

!= 不為 數據轉換 none sql數據庫 column varchar 查找 tab

大多數的數據庫引擎(到現在據我們所知的除了sqlite的每個sql數據庫引擎)都使用靜態的、剛性的類型,使用靜態類型,數據的類型就由它的容器決定,這個容器是這個指被存放的特定列。

Sqlite使用一個更一般的動態類型系統,sqlite中,值的數據類型跟值本身相關,而不是與它的容器相關。Sqlite的動態類型系統和其他數據庫的更為一般的靜態類型系統相兼容,但同時,sqlite中的動態類型允許它能做到一些傳統剛性類型數據庫所不可能做到的事。

1. 存儲類和數據類型

每個存放在sqlite數據庫中(或者由這個數據庫引擎操作)的值都有下面中的一個存儲類:

l NULL,值是NULL

l INTEGER,值是有符號整形,根據值的大小以1,2,3,4,6或8字節存放

l REAL,值是浮點型值,以8字節IEEE浮點數存放

l TEXT,值是文本字符串,使用數據庫編碼(UTF-8,UTF-16BE或者UTF-16LE)存放

l BLOB,只是一個數據塊,完全按照輸入存放(即沒有準換)

從上可以看出存儲類比數據類型更一般化。比如INTEGER存儲類,包括6中不同長度的不同整形數據類型,這在磁盤上造成了差異。但是只要INTEGER值被從磁盤讀出進入到內存進行處理,它們被轉換成最一般的數據類型(8-字節有符號整形)。

Sqlite v3數據庫中的任何列,除了整形主鍵列,可以用於存儲任何一個存儲列的值。sql語句中的中所有值,不管它們是嵌入在sql文本中或者是作為參數綁定到一個預編譯的sql語句,它們的存儲類型都是未定的。在下面描述的情況中,數據庫引擎會在查詢執行過程中在數值(numeric)存儲類型(INTEGER和REAL)和TEXT之間轉換值。

1.1布爾類型

Sqlite沒有單獨的布爾存儲類型,它使用INTEGER作為存儲類型,0為false,1為true

1.2 Date和Time Datatype

Sqlite沒有另外為存儲日期和時間設定一個存儲類集,內置的sqlite日期和時間函數能夠將日期和時間以TEXT,REAL或INTEGER形式存放

l TEXT 作為IS08601字符串("YYYY-MM-DD HH:MM:SS.SSS")

l REAL 從格林威治時間11月24日,4174 B.C中午以來的天數

l INTEGER 從 1970-01-01 00:00:00 UTC以來的秒數

程序可以任意選擇這幾個存儲類型去存儲日期和時間,並且能夠使用內置的日期和時間函數在這些格式間自由轉換

2.0 類型近似

為了使sqlite和其他數據庫間的兼容性最大化,sqlite支持列上“類型近似”的觀點,列的類型近似指的是存儲在列上數據的推薦類型。這裏必須記住一點,這個類型是被推薦,而不是必須的。任何列仍然能存儲任意類型的數據。只是一些列,給予選擇的話,將會相比於其他的一些類型優選選擇一些存儲類型,這個列優先選擇的存儲類型被稱為它的“近似”。

每個sqlite3數據庫中的列都被賦予下面類型近似中的一種:

l TEXT

l NUMERIC

l INTEGER

l REAL

l NONE

具有TEXT近似的列可以用NULL,TEXT或者BLOB類型存儲數據。如果數值數據被插入到具有TEXT近似的列,在被存儲前被轉換為文本形式

一個有NUMERIC近似的列可以使用1中的所有5中存儲類來存儲數據。當文本數據被存放到NUMERIC近似的列中,這個文本的存儲類被轉換到INTEGER或REAL(根據優先級順序),如果這個轉換是無損的話。對於TEXT和REAL存儲類間的轉換,如果數據的前15位的被保留的話sqlite就認為這個轉換是無損的、可反轉的。如果TEXT到INTEGER或REAL的轉換不可避免的會造成損失,那麽數據將使用TEXT存儲類存儲。不會企圖去轉換NULL或BLOB值。

一個字符串可能看起來像浮點數據,有小數點或指數符號,但是只要這個數據可以使用整形存放,NUMERIC近似就會將它轉換到整形。比如,字符串 ‘3.0e+5‘存放到一個具有NUMERIC近似的列中,被存為300000,而不是浮點型值300000.0。

具有INTEGER近似的列和具有NUMERIC近似的列表現相同。它們之間的差別僅處於轉換描述上。

具有REAL近似的列和具有NUMERIC近似的列一樣,除了它將整形數據轉換成浮點型形式。

具有NONE近似的列不會優先選擇一個存儲列,也不會強制將數據從一個存儲類轉換到另外一個類。

2.1 列近似的決定因素

列的近似由這個列的聲明類型所決定,根據下面的順序的規則:

<1> 如果聲明類型包含”INT”字符串,那麽這個列被賦予INTEGER近似

<2> 如果這個列的聲明類型包含”CHAR”,”CLOB”,或者”TEXT”中的任意一個,那麽這個列就有了TEXT近似。註意類型VARCHAR包含了”CHAR”字符串,那麽也就被賦予了TEXT近似

<3> 如果列的聲明類型中包含了字符串”BLOB”或者沒有為其聲明類型,這個列被賦予NONE近似

<4> 其他的情況,列被賦予NUMERIC近似

上面規則額順序對於決定列的近似很重要。一個列的聲明類型為”CHARINT”的話同時會匹配規則<1>和<2>,但是第一個規則占有優先級所以這個列的近似將是INTEGER。

2.2 近似名稱例子

下面這個表顯示了多少來自更傳統的SQL操作的普通數據類型名稱,使用上一節中的5個規則,被轉換到近似類型。這個表只顯示了sqlite能夠接受的數據類名稱的一個子集。註意到跟隨類型名的圓括號內的數值參數(如:”VARCHAR(255)”)被sqlite忽略—sqlite不在字符串、BLOBS或者數值的長度上強加任何長度限制(除了一個全局的SQLITE_MAX_LENGTH限制)。

來自create table語句或者強轉語句的範例類型名

產生的近似

用於決定近似的規則

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
no datatype specified

NONE

3

REAL
DOUBLE
DOUBLE PRECISION
FLOAT

REAL

4

NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIME

NUMERIC

5

註意到聲明類型為”FLOATING POINT”將被賦予INTEGER近似,而不是REAL近似,因為在”POINT”中的”INT”。聲明類型為”STRING”的將被賦予NUMERIC,而不是TEXT(因為上述表中定義的類型中不存在STRING這一類型,它被歸於到規則<4>中,屬於其他情況)。

(從上面可以看出,sqlite3只是從聲明類型字符串中去查找它知道的聲明類型,比如”XINT”將被賦予INTEGER近似因為這個字符串裏面有”INT”,所以這裏並不需要一個單獨的正確的聲明類型,而是只要聲明類型字符串裏面包含了sqlite所知道的聲明類型即可)

2.3 列近似操作例子

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

); //這裏根據聲明類型確定了列的類型近似

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

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

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

(這裏的第四個值,對應的列是REAL近似的,傳輸的值整形的,但是根據REAL近似的規則它會將它轉換為real型數據)

// 數據塊(BLOB)不管是什麽列近似都一直存為BLOB類型

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也不受列近似影響

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 比較表達式

Sqlite v3有一系列有用的比較操作符,包括 "=", "==", "<", "<=", ">", ">=", "!=", "<>", "IN", "NOT IN", "BETWEEN", "IS", 和 "IS NOT"

3.1 排序

比較操作的結果基於操作數的存儲類型,根據下面的規則:

l 存儲類型為NULL的值被認為小於其他任何的值(包括另一個存儲類型為NULL的值)

l 一個INTEGER或REAL值小於任何TEXT或BLOB值。當一個INTEGER或REAL值與另外一個INTEGER或REAL值比較的話,就執行數值比較

l TEXT值小於BLOB值。當兩個TEXT值比較的時候,就根據序列的比較來決定結果

l 當兩個BLOB值比較的時候,使用memcmp來決定結果

3.2 比較操作數的近似(Affinity)

Sqlite可能在執行一個比較之前會在INTEGER,REAL或TEXT之間轉換比較值。是否在比較操作之前發生轉換基於操作數的近似(類型)。操作數近似(類型)由下面的規則決定:

l 對一個列的簡單引用的表達式與這個列有相同的affinity,註意如果X和Y.Z是列名,那麽+X和+Y.Z均被認為是用於決定affinity的表達式

l 一個”CAST(expr as type)”形式的表達式與用聲明類型為”type”的列有相同的affinity

l 其他的情況,一個表達式為NONE affinity

3.3 在比較前的類型轉換

只有在轉換是無損、可逆轉的時候“應用近似”才意味著將操作數轉換到一個特定的存儲類。近似在比較之前被應用到比較的操作數,遵循下面的規則(根據先後順序):

l 如果一個操作數有INTEGER,REAL或NUMERIC近似,另一個操作數有TEXT或NONE近似,那麽NUMERIC近似被應用到另一個操作數

l 如果一個操作數有TEXT近似,另一個有NONE近似,那麽TEXT近似被應用到另一個操作數

l 其他的情況,不應用近似,兩個操作數按本來的樣子比較

表達式"a BETWEEN b AND c"表示兩個單獨的二值比較” a >= b AND a <= c”,即使在兩個比較中不同的近似被應用到’a’。

3.4 比較舉例

CREATE TABLE t1(

a TEXT, -- text affinity

b NUMERIC, -- numeric affinity

c BLOB, -- no affinity

d -- no affinity

);

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

從這裏可以看出,假如可以使用3.1中的規則進行比較的話,就不需要進行類型轉換,否則的話就要進行類型轉換

4.0 操作符

所有的數學操作符(+, -, *, /, %, <<, >>, &, |),在被執行前,都會將兩個操作數都轉換為數值存儲類型(INTEGER和REAL)。即使這個轉換是有損和不可逆的,轉換仍然會執行。一個數學操作符上的NULL操作數將產生NULL結果。一個數學操作符上的操作數,如果以任何方式看都不像數字,並且又不為空的話,將被轉換為0或0.0。

http://www.cnblogs.com/kfqcome/archive/2011/06/27/2137000.html

sqlite3中的數據類型