sqlite数据类型

官方文档:http://www.sqlite.org/datatype3.html#affinity

绝大多数数据库引擎都是用静态(除SQLite之外的其他所有SQL数据库引擎), 严格的数据类型. 使用静态数据类型的情况下, 数据类型由值的容器决定– 也就是存储该值的列.
SQLite使用一个更加通用的类型系统. 在SQLite中, 值的数据类型是和值本身相关联的, 而不是其容器决定的. SQLite的动态数据类型向后兼容其他较常见的使用静态数据类型的数据库系统, 即在静态数据类型数据库系统上使用的SQL语句同样适用于SQLite. 但是在SQLite上进行的动态数据类型操作却不可能适用于传统的静态数据类型的数据库系统.

注意:类型名后括号里的数值型的参数声明(例如: “VARCHAR(255)”)将被SQLite忽略– SQLite并不接受字符串, BLOBs和数值型数据的强制的长度限制(除了全局的SQLITE_MAX_LENGTH限制规则).

_db = [FMDatabase databaseWithPath:databasePath];
_dbChar = [FMDatabase databaseWithPath:databaseCharPath];
[_db open];
[_dbChar open];
[_db executeUpdate:@"create table lbx (name text)"];
[_dbChar executeUpdate:@"create table lbx (name char(250))"];
for (NSInteger i = 0; i < 100000; i++) {
[_db executeUpdate:@"insert into lbx values ('a')"];
[_dbChar executeUpdate:@"insert into lbx values ('a')"];
}
[_dbChar close];
[_db close];

Snip20170312_1.png

1、Storage Classes and Datatypes

每一个存储在SQLite数据库系统中的值(或者被数据库引擎操纵)必定属于以下几个类型中的一个:

  • NULL. 值为NULL
  • INTEGER. 有符号的整形数值, 按数值大小以1,2,3,41,2,3,4,6或8字节存储.
  • REAL. 浮点数值, 以8字节IEEE标准浮点数存储.
  • TEXT. 文本字符串, 以数据库的字符编码方式存储(UTF-8, UTF-16BE或者UTF-16LE).
  • BLOB. 该值是一个BLOB数据, 将以与输入时一致的二进制码存储.

存储类型相比数据类型是更加通用的. 比如说INTEGER存储类包含6种不同长度的整形数据类型. 虽然6种类型是以不同方式存储在磁盘上, 但INTEGER数据一旦从磁盘里读取到内存中用于处理是, 所有的6种类型都会被转换为最通用的数据类型(8字节有符号整数). 因此大部分情况下, “存储类型”与”数据类型”并没有什么分别, 可以相互替换表示.

SQLite3中的任何列, 除INTEGER PRIMARY KEY列之外, 可以用来存储以上提到的任何类型(storage class)的值.

SQL语句中所有的值, 无论他们是以纯文本方式嵌入到SQL语句中还是以预编译方式绑定到SQL语句的参数都有一个隐含的存储类型.

1.1 Boolean Datatype

SQLite没有单独的布尔存储类型. 在SQLite中, 布尔值, 真被存储为整形数值1, 假被存储为整形数值0.

1.2 Date and Time Datatype

SQLite没有单独的日期和时间存储类型. 作为替代的是,SQLite内建的日期和时间函数可用于处理以TEXT, REAL或INTEGER方式存储的日期:

  • TEXT 以ISO8601标准表示的字符串(“YYYY-MM-DD HH:MM:SS.SSS”).
  • REAL 以Julian day计算(儒略日), 公元前4714年11月24日至日期所经历的天数.
  • INTEGER 以Unix时间方式表示, 即1970-01-01 00:00:00 UTC至日期所经历的秒数.

在应用中可以自由地使用以上3种方式存储日期和时间, 也可以用内建的日期和时间函数在它们之间做任意的转换.

2.0 Type Affinity (亲和类型)

具有严格数据类型的SQL数据库通常会自动将数值转换为合适的数据类型。如下:

CREATE TABLE t1(a INT, b VARCHAR(10));
INSERT INTO t1(a,b) VALUES('123',456);

严格数据类型的数据库在插入数据前会将字符串‘123’转换为整型123,将整型456转换为字符串‘456’。

为了使SQLite更加兼容其他的数据库引擎, SQLite支持列”亲和类型”概念. 所谓的列的亲和类型就是在该列中推荐使用的存储类型. 必须注意的是, 这里只是推荐的类型, 而非必须使用的类型. 任何列依然可以存储任何类型的数据. 这只是说, 在一些列中我们会给予一些选择, 这将使得我们会优先使用一种存储类型. 优先使用的存储类型被叫做该列的”亲和(affinity)”.
SQLite3的每列亲和类型是一下几种之一:

  • TEXT
  • NUMERIC
  • INTEGER
  • REAL
  • BLOB(过去成为NONE)

具有TEXT亲和类型的列存储的数据类型有NULL, TEXT和BLOB. 如果将数值型的数据插入到具有TEXT亲和类型的列中, 那么在该值被存储前将会被转换为字符型.

具有NUMERIC亲和类型的列可存储所有5种存储类型的值. 当把文字信息插入到NUMERIC列中, 在不损失精度且转换可逆的情况下, 该段文字的存储类型将被转换至INTEGER或REAL类型. 在转换TEXT和REAL时, 如果字段的前15位十进制数能被保留的话, 那么SQLite将认为该转换是无损和可逆的. 如果将TEXT无损转换为INTEGER或REAL的过程被判断为不可能完成的话, 那么该字段信息将会用TEXT存储类型存入数据库.SQLite在任何情况下都不会尝试转换NULL或BLOB型数据信息.

如果一个字符串是有小数点的浮点数有指数符号的浮点数, 但只要该值能被表示成一个整型数据, 则NUMERIC亲和将会将其转换成一个整型数值. 因此, ‘3.0e+5’在具有NUMERIC亲和的列下将被存储为300000, 而不是值为300000.0浮点数.

具有INTEGER亲和类型的列与具有NUMERIC亲和类型的列的规则一致. INTEGER和NUMERIC亲和类型的唯一明显的区别是在CAST表达式中.

具有REAL亲和类型的列与NUMERIC亲和类型表现一致, 除了它会强制把整型数据转换至浮点形式(一个内部的优化是, 将绝对值很小的浮点数存入具有REAL亲和类型的列时, 为了节省数据占用空间, 该值将以整型写入到磁盘中, 在读出时会被自动转换回浮点数. 该优化在SQL层面上是完全不可见的, 只能在检测原始数据库文件比特序列时被发现).
具有BLOB亲和类型的列不会优先使用任何一个存储类型, 也不会强制地将一种数据存储类型转换为其他存储类型.

2.1 Determination Of Column Affinity

一个列的亲和类型将会被该字段的声明类型所决定, 按顺序地根据以下规则将可以得出亲和类型:

  1. 如果声明类型包含字符串”INT”, 将会被赋予INTEGER亲和类型.
  2. 如果声明类型包含字符串”CHAR”, “CLOB”或者”TEXT”, 那么该字段将被赋予TEXT亲和类型. 注意因为VARCHAR包含”CHAR”, 故也被赋予TEXT亲和类型.
  3. 如果声明类型包含字符串”BLOB”或者没有指定类型, 那么该字段将拥有”NONE”亲和类型.
  4. 如果声明类型包含字符串”REAL”, “FLOA”或者”DOUB”, 那么该字段将拥有REAL亲和类型.
  5. 否则, 亲和类型将是NUMERIC.

注意以上的亲和类型顺序是是十分重要的. 如果一个字段的声明类型是”CHARINT”, 它将符合规则1和规则2, 但是规则1的优先权高于规则2, 所以该字段的亲和类型将是INTEGER.

2.2 Affinity Name Examples

下表展示了传统SQL实现的通用数据类型在上面5条规则的作用下是如何被转换成相应的亲和类型的. 下表只展示了SQLite支持的数据类型名的一小部分.

Example Typenames From The CREATE TABLE Statement or CAST Expression Resulting Affinity Rule Used To Determine Affinity
INT、INTEGER、TINYINT、SMALLINT、MEDIUMINT、BIGINT、UNSIGNED BIG INT、INT2、INT INTEGER 1
CHARACTER(20)、VARCHAR(255)、VARYING CHARACTER(255) 、NCHAR(55)、NATIVE CHARACTER(70)、NVARCHAR(100)、TEXT、CLOB TEXT 2
BLOB、no datatype specified BLOB 3
REAL、DOUBLE、DOUBLE PRECISION、FLOAT REAL 4
NUMERIC、DECIMAL(10,5)、BOOLEAN、DATE、DATETIME NUMERIC 5

2.2 Affinity Of Expressions

表格的所有列都有亲和类型,但是表达式(expression)不一定有亲和类型。表达式的亲和由下面的规则决定:

  • 如果IN或NOT IN表达式的操作数是个列表,则该操作数没有亲和,如果操作数是select语句,则操作数的亲和为select结果集的亲和。
  • 当一个表达式引用一个表格(真正的表格,不是视观表或者子查询)的一个列的时候,表达式的亲和与表格的列的亲和一样。
  • 括着列名的括号是被忽略的,所以如果X和Y.Z是列名,则(X)和(Y.Z)也被当作列名,从而表达式拥有和对应的列相同的亲和
  • 所有作用在列名上的运算符(包括单目运算符‘+’),会 将列名转换为没有亲和的表达式。所以,即使X和Y.Z是列名,表达式+X和+Y.Z不是列名,也没有亲和。
  • “CAST(expr AS type)”结构的表达式的亲和与定义为type类型的列的亲和一样。
  • 此外,表达式都没有亲和

2.3. Column Affinity Behavior Example

视观表的列或者from结构的子查询都是实现视观表或者子查询的select语句的结果集中的表达式。所以,视观表中的列或者子查询的亲和由上面表达式亲和规则决定。

e.g
CREATE TABLE t1(a INT, b TEXT, c REAL);
CREATE VIEW v1(x,y,z) AS SELECT b, a+c, 42 FROM t1 WHERE b!=11;
v1.x的亲和与t1.b(INTEGER)的亲和一样,因为v1.x和t1.b对应,而v1.y和v1.z没有亲和,因为他们分别对应表达式a+c和42,而表达式是没有亲和的。

2.4. Column Affinity Behavior Example

下面的sql示范了在向表格插入数据的时候,sqlite怎样利用亲和进行数据类型转换
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
);

-- 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 Comparison Expressions

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

3.1 Sort Order

比较操作的结果基于操作数的存储类型,根据下面的规则:

  • 存储类型为NULL的值被认为小于其他任何的值(包括另一个存储类型为NULL的值)
    *一个INTEGER或REAL值小于任何TEXT或BLOB值。当一个INTEGER或REAL值与另外一个INTEGER或REAL值比较的话,就执行数值比较
  • TEXT值小于BLOB值。当两个TEXT值比较的时候,就根据序列的比较来决定结果
  • 当两个BLOB值比较的时候,使用memcmp来决定结果

3.2Type Conversions Prior To Comparison(Affinity)

Sqlite可能在执行一个比较之前会在INTEGER,REAL或TEXT之间转换比较值。
只有在转换是无损、可逆转的时候,“apply affinity”才意味着将操作数转换到一个特定的存储类。是否在比较操作之前发生转换基于下面的规则决定:

  • 如果一个操作数的亲和类型为INTEGER,REAL或NUMERIC,另一个操作数亲和类型为TEXT或BLOB或无亲和类型,那么NUMERIC亲和类型被应用到另一个操作数
  • 如果一个操作数亲和类型为TEXT,另一个无亲和类型,那么TEXT亲和类型被应用到另一个操作数
  • 其他的情况,亲和类型不被应用,两个操作数按本来的样子比较

表达式"a BETWEEN b AND c"表示两个单独的二值比较” a >= b AND a <= c”,即使在两个比较中不同的近似被应用到’a’。“x IN (SELECT y ...)”形式的比较的数据类型转换就像“x = y”的比较一样。表达式“a IN (x, y , z, ...)”等于"a = +x OR a = +y OR a = +z OR ...",也就是说IN运算符右侧的值是没有亲和类型的。

3.3. Comparison Example

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 Operators

所有的数学操作符(+, -, *, /, %, <<, >>, &, |),在被执行前,都会将两个操作数都转换为数值存储类型(INTEGER和REAL)。即使这个转换是有损和不可逆的,转换仍然会执行。一个数学操作符上的NULL操作数将产生NULL结果。一个数学操作符上的操作数,如果以任何方式看都不像数字,并且又不为空的话,将被转换为0或0.0。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容