• SQLite数据类型


    绝大多数的SQL数据库引擎使用静态的、硬性的类型,对于静态类型,数据的数据类型由存储它的容器决定(也就是存储该数据的列)。

    SQLite使用动态类型,也就是数据类型由数据本身决定,与存储容器无关。所以在创建表时,可以忽略列的数据类型,不过这样做并不好,不但表结构看起来不清晰,万一哪天需要更换数据库就会更麻烦。

    SQLite的动态类型与其它数据库引擎的普通静态类型相兼容,这样程序员可以写出移植性更好的SQL语句。而且,SQLite的动态类型允许它能做一些使用传统硬性类型的数据库所做不到的事。

    1 存储类别(storage class)与数据类型(datatype)

    存储在SQLite数据库中的数据属于下面这些存储类别之一:

    1. NULL:值为NULL
    2. INTEGER:有符号整形,根据值的大小以1、2、3、4、6或8字节存储
    3. REAL:浮点类型,以8字节IEEE浮点数存储
    4. TEXT:文本字符串,使用数据库编码(UTF-8、UTF-16BE或者UTF-16LE)存储
    5. BLOB:二进制数据块,完全按照输入存放(即没有转换)

    存储类别比数据类型更一般化(general)。比如INTEGER,它包含6种不同长度的整数(integer)数据类型,它们在磁盘存储上存在差异(This makes a difference on disk)。但是只要INTEGER数据从磁盘读入到内存进行处理,它们就会被转换成最普通的8字节有符号整数(integer)数据类型。

    SQLite3数据库中的任何列(除了整形主键(INTEGER PRIMARY KEY)列),可以用于存储任何一个存储类别的值。SQL语句中的所有值(value),无论是嵌入在SQL语句中,或者作为参数绑定到一个预编译SQL语句,它们都有一个隐式的存储类别。在下述情况下,数据库引擎会在查询执行过程中在数值(numeric)存储类别(INTEGER和REAL)和TEXT存储类别之间转换。

    (1)布尔(Boolean)数据类型

    SQLite没有单独的布尔存储类别,它使用INTEGER存储类别,0作为false,1作为true。

    (2) 日期和时间(Date and Time)数据类型

    SQLite没有为日期和时间专门预留一个的存储类别,SQLite内置的日期和时间函数能够将日期和时间以TEXT,REAL或INTEGER类型存储。

    1. TEXT:作为IS08601字符串(”YYYY-MM-DD HH:MM:SS.SSS”)
    2. REAL:朱利安(Julian)天数,从格林威治公元前4714年12月24日中午以来的天数
    3. INTEGER:Unix时间,从UTC(协调世界时)1970-01-01 00:00:00以来的秒数

    应用程序可以选择这三种格式之一来存储日期与时间,并且可以使用SQLite内置的日期与时间函数在这些格式之间自由转换。

    2 类型近似(Type Affinity)

    为了使SQLite与其它数据库引擎之间保持最大的兼容性,SQLite支持列(columns)上的类型近似的概念。列的类型近似是指存储在列上的数据的推荐类型,重要的一点是这个类型仅仅是推荐(recommend)类型,并不是必须的。任何列仍然能够存储任意类型的数据,仅仅是有些列,如果给予选择的话,会优先选择某一个存储类别,这个列优先选择的存储类型被称为它的“近似”。

    每个SQLite3数据库中的列都会被赋予下面类型近似中的一种:

    1. TEXT
    2. NUMERIC
    3. INTEGER
    4. REAL
    5. NONE

    具有TEXT近似的列可以使用NULL、TEXT或BLOB存储类别来存储数据。如果数值数据被插入到具有TEXT近似的列,会在被存储前转换为文本(text)。

    具有NUMERIC近似的列可以使用所有的五种存储类别来存储数据。当文本数据被插入(insert)到NUMERIC近似的列中,它的存储类别会被转换为INTEGER或REAL(按照优先级顺序),假如这种转换是无损和可逆的话。对于TEXT和REAL存储类别之间的转换,如果数据的前15个有效位的被保留的话,SQLite就认为这个转换是无损的、可逆的。如果TEXT到INTEGER或REAL的转换不可避免的会造成损失,那么数据将使用TEXT存储类别存储。不会试图去转换NULL或BLOB值。

    一个字符串可能看起来像浮点数据,有小数点和/或指数符号,但是只要这个数据可以使用整形存放,NUMERIC近似就会将它转换为整形。所以,字符串“3.0e+5”存储到一个NUMERIC近似的列中,是以整形数300000的形式,而不是浮点值300000.0。

    具有INTEGER近似的列和具有NUMERIC近似的列的行为相同,它们之间的区别仅仅在于“转换表达式(CAST expression)”上。

    具有REAL近似的列和具有NUMERIC近似的列的行为相似,除了它强制的将整形数转换为浮点表示形式。

    具有NONE近似的列不会优先选择一个存储类别,也不会试图强制将数据从一个存储类别转换到另外一个存储类别。

    (1)列近似如何判定(Determination Of Column Affinity)

    列的近似由这个列的声明类型所决定,所依据的规则按顺序排列如下:

    1. 1> 如果声明类型包含“INT”字符串,那么这个列被赋予INTEGER近似
    2. 2>如果这个列的声明类型包含字符串“CHAR”、“CLOB”或“TEXT”中的任何一个,那么这个列就有了TEXT近似。注意类型VARCHAR包含了字符串“CHAR”,因此被赋予TEXT近似。
    3. 3>如果列的声明类型包含字符串“BLOB”,或者没有指定类型,这个列被赋予NONE近似
    4. 4>如果列的声明类型包含字符串“REAL”、“FLOA”或“DOUB”中的任何一个,这个列将是REAL近似。
    5. 5>其他情况,列被赋予NUMERIC近似

    上面规则的顺序对于决定列的近似非常重要。一个列的声明类型为“CHARINT”的话会同时匹配规则1和2,但是第1个规则占有优先级所以这个列的近似将是INTEGER。

    (2)近似名称示例(Affinity Name Examples)

    下表展示了来自更传统的SQL操作的普通数据类型名称,使用上一节的5个规则,被转换为近似类型。这个表只显示了SQLite能够接受的数据类型名称的一小部分。注意到跟随类型名称的圆括号内的数值参数(如:“VARCHAR(255)”)将被SQLite忽略——SQLite不在字符串、BLOBS或者数值的长度上施加任何长度限制(只有一个全局的SQLITE_MAX_LENGTH限制)。

    注意声明类型为“FLOATING POINT”将被赋予INTEGER近似,而不是REAL近似,因为在“POINT”结尾含有“INT”。声明类型为“STRING”将被赋予NUMERIC近似,而不是TEXT近似(因为上述表中定义的类型名称中不存在STRING,它被归于近似规则的第5条,属于其他情况)。

    (从上面可以看出,SQLite只是从声明类型字符串中去查找它知道的声明类型,比如“XINT”将被赋予INTEGER近似因为这个字符串里面有“INT”,所以这里并不需要一个单独的正确的声明类型,而是只要声明类型字符串里面包含了SQLite所知道的声明类型即可)

    (3) 列近似行为的例子(Column Affinity Behavior Example)

    3 比较表达式

    SQLite3有一系列通常的比较操作符,包括“=”、“==”、“<”、“<=”、“>”、“>=”、“!=”、“<>”、“IN”、“NOT IN”、“BETWEEN”、“IS”和“IS NOT”。

    (1)排序

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

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

    (2)比较操作数的近似(Affinity Of Comparison Operands)

    SQLite可能在执行一个比较操作之前会在INTEGER,REAL和/或TEXT存储类别之间转换比较值。是否在比较操作之前发生转换基于操作数的(类型)近似。操作数(类型)近似由下面的规则决定:

    1. 对一个列的简单引用的表达式与这个列有相同的近似(affinity),注意如果X和Y.Z是列名,那么+X和+Y.Z均被认为是决定近似的表达式。
    2. 一个“CAST(expr as type)”形式的表达式与声明类型为“type”的列有相同的近似。
    3. 其他情况,一个表达式为NONE近似。

    (3) 比较之前的类型转换(Type Conversions Prior To Comparison)

    只有在转换是无损、可逆的情况下,“应用近似(apply affinity)”才意味着将操作数转换到一个特定的存储类别。在比较操作之前,应用到其操作数的近似(affinity),需要依据的规则按顺序排列如下:

    1. 如果一个操作数拥有INTEGER,REAL或NUMERIC近似,另一个操作数拥有TEXT或NONE近似,那么NUMERIC近似被应用到另一个操作数
    2. 如果一个操作数有TEXT近似,另一个有NONE近似,那么TEXT近似被应用到另一个操作数
    3. 其他情况下不应用近似,两个操作数按原样比较

    表达式“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操作符右侧的值(示例中的x、y和z)被认为没有近似(have no affinity),即使它们碰巧是列值或CAST表达式。

    (4) 比较示例

    对于示例程序中的比较操作反写,比如“a<40”改写为“40>a”,比较结果也是相同的。

    从这里可以看出,假如可以使用3.1中的规则进行比较的话,就不需要进行类型转换,否则的话就要进行类型转换。

    4 操作符

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

    5 排序、分组和组合SElECT语句(Sorting, Grouping and Compound SELECTs)

    当查询结果使用ORDER BY子句排序时,存储类别为NULL的值将排在最前面,接着是存储类别为INTEGER和REAL的值按数值排序,然后是TEXT值按序排列,最后是BLOB值以memcmp()排序出现。在排序之前不会发生存储类别的转换。

    使用GROUP BY子句分组值时,如果值的存储类别不同,则它们是不同的。不过对于存储类别为INTEGER和REAL的值,如果它们在数值相等,它们就是相等的。使用GROUP BY子句分组的值不会应用(类型)近似(affinity)规则。

    SELECT组合查询的操作符UNION、INTERSECT和EXCEPT将对于所操作的值执行隐式比较(perform implicit comparisons betweent values),对于这些比较的操作数不会应用(类型)近似(affinity)规则。

    6 Collating序列(Sequences)

    SQLite使用collating序列或者collating函数(function)来比较两个字符串的大小,SQLite有3个内置的collating函数:BINARY、NOCASE和RTRIM

    1. BINARY:使用memcmp()比较字符串数据,不管文本使用何种编码
    2. NOCASE:与BINARY相同,但是ASCII码的26个大写字符将会在比较之前转换为其小写形式。
    3. RTRIM:与BINARY相同,但是尾部的空格字符将被忽略。

    应用程序可以使用sqlite3_create_collation()接口注册额外的collating函数。

    (1)Assigning Collating Sequences from SQL

    表中的每一个列都有一个相关联的collating函数,如果没有显示定义,默认为BINARY。列定义(column definition)的COLLATE子句用来定义列的替代(alternative)collating函数。

    对于二值比较操作符(=、<、>、<=、>=、!=、IS和IS NOT)使用哪一个collating函数,其依据的规则按顺序排列如下:

    1. 如果任何一个操作数使用后缀COLLATE操作符赋予了一个显示的collating函数,那么这个显示的collating函数就用来比较,其中左操作数的collating函数的优先使用。
    2. 如果任何一个操作数是一个列(column),那么这个列的collating函数将比左操作数的collating函数更优先使用。
    3. 其它情况下,使用BINARY。

    An operand of a comparison is considered to have an explicit collating function assignment (rule 1 above) if any subexpression of the operand uses the postfix COLLATE operator. Thus, if aCOLLATE operator is used anywhere in a comparision expression, the collating function defined by that operator is used for string comparison regardless of what table columns might be a part of that expression. If two or moreCOLLATE operator subexpressions appear anywhere in a comparison, the left most explicit collating function is used regardless of how deeply the COLLATE operators are nested in the expression and regardless of how the expression is parenthesized.

    The expression “x BETWEEN y and z” is logically equivalent to two comparisons “x >= y AND x <= z” and works with respect to collating functions as if it were two separate comparisons. The expression “x IN (SELECT y …)” is handled in the same way as the expression “x = y” for the purposes of determining the collating sequence. The collating sequence used for expressions of the form “x IN (y, z, …)” is the collating sequence of x.

    Terms of the ORDER BY clause that is part of a SELECTstatement may be assigned a collating sequence using the COLLATE operator, in which case the specified collating function is used for sorting. Otherwise, if the expression sorted by an ORDER BY clause is a column, then the collating sequence of the column is used to determine sort order. If the expression is not a column and has no COLLATE clause, then the BINARY collating sequence is used.

    (2) Collation Sequence Examples

    The examples below identify the collating 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 collating sequence used, in the case of numeric, blob or NULL values(注意:如果是numeric、blob或者NULL类型的值,就不需要进行文本比较了,当然也就不会使用collating序列了)。

  • 相关阅读:
    使用PaintCode便捷地实现动画效果
    程序员常用markdown语法记忆小结之博客园markdown编辑器的效果
    kafka-重复消费-1
    nosql
    ThreadLocal
    内存溢出、内存泄漏
    springboot邮件服务
    三次握手、四次挥手
    悲观锁乐观锁简单整理
    beanstalkd
  • 原文地址:https://www.cnblogs.com/qq1223558/p/3056448.html
Copyright © 2020-2023  润新知