首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Datatypes In SQLite version 2

数据类型在 SQLite 版本2中

1.0 无类型

SQLite 是“无类型的”。这意味着您可以在任何表的任何列中存储任何类型的数据,而不管该列的已声明数据类型。(请参阅下面第2.0节中对此规则的一个例外。)此行为是一个功能,而不是一个错误。数据库应该存储和检索数据,数据库对数据的格式应该没有关系。在大多数其他 SQL 引擎中发现的强大的键入系统,并且在 SQL语言规范中被编码是一种错误特性 - 这是一个例子通过界面显示的实现。SQLite 试图通过允许您将任何类型的数据存储到任何类型的列中并允许数据类型规范中的灵活性来克服这种错误特性。

SQLite 的数据类型是零个或多个名称的任意序列,可选地后跟带有一个或两个带符号整数的带括号的列表。特别注意,数据类型可能是零个或多个名称。这意味着就 SQLite 而言,空字符串是有效的数据类型。因此,您可以声明表中每个列的数据类型未指定的位置,如下所示:

代码语言:javascript
复制
CREATE TABLE ex1(a,b,c);

尽管 SQLite 允许省略数据类型,但将它包含在 CREATE TABLE 语句中仍然是一个好主意,因为数据类型通常可以为其他程序员提供有关打算放入列的内容的良好提示。如果您将代码移植到另一个数据库引擎,那么其他引擎可能需要某种数据类型。SQLite 接受所有通常的数据类型。例如:

代码语言:javascript
复制
CREATE TABLE ex2(
  a VARCHAR(10),
  b NVARCHAR(15),
  c TEXT,
  d INTEGER,
  e FLOAT,
  f BOOLEAN,
  g CLOB,
  h BLOB,
  i TIMESTAMP,
  j NUMERIC(10,5)
  k VARYING CHARACTER (24),
  l NATIONAL VARYING CHARACTER(16)
);

等等。基本上任何名称序列都可以选择跟随一个或两个带括号的有符号整数。

2.0 INTEGER 主键

SQLite 无类型的一个例外是一个类型为 INTEGER PRIMARY KEY 的列。(并且必须使用“INTEGER”而不是“INT”。INT PRIMARY KEY 类型的列与其他任何类型无关)。INTEGER PRIMARY KEY 列必须包含一个32位有符号整数。任何尝试插入非整数数据都会导致错误。

INTEGER PRIMARY KEY 列可用于实现等效的 AUTOINCREMENT。如果您尝试将 NULL 插入到 INTEGER PRIMARY KEY列中,则该列实际上将被填充的整数比表中已有的最大键大1。或者,如果最大的键是2147483647,那么该列将填充一个随机整数。无论哪种方式,INTEGER PRIMARY KEY 列都将被分配一个唯一的整数。您可以使用sqlite_last_insert_rowid() API 函数或在随后的 SELECT 语句中使用last_insert_rowid() SQL 函数来检索此整数。

3.0 比较和排序顺序

为了决定允许哪些数据存储在列中,SQLite 是无类型的。但是,在对数据进行排序和比较时,一些类型概念会发挥作用。出于这些目的,列或表达式可以是以下两种类型之一:数字文本。排序或比较可能会给出不同的结果,具体取决于正在对哪些类型的数据进行排序或比较。

如果数据是文本类型,则比较由标准C数据比较函数 memcmp()strcmp()确定。比较将逐个查看来自两个输入的字节,并返回第一个非零差值。字符串是'\ 000'结尾,所以较短的字符串在较长的字符串之前进行排序,就像您期望的那样。

对于数字数据,这种情况更为复杂。如果两个输入都看起来像格式良好的数字,则使用 atof()将它们转换为浮点值并进行数值比较。如果一个输入不是一个正确的数字,而是另一个输入,那么该数字被认为小于非数字。如果两个输入都不是格式正确的数字,则使用 strcmp()进行比较。

不要被列可能有“数字”数据类型的事实所迷惑。这并不意味着该列只能包含数字。它仅仅意味着如果列中包含一个数字,该数字将按数字顺序排序。

对于文本和数字值,NULL 都会在任何其他值之前排序。使用诸如“<”或“> =”等运算符的任何值与 NULL 的比较始终是错误的。

4.0 SQLite 如何确定数据类型

对于 SQLite 2.6.3及更早版本,所有值都使用数字数据类型。文本数据类型出现在2.7.0及更高版本中。在续集中,假设您正在使用 SQLite 的2.7.0或更高版本。

对于表达式,结果的数据类型通常由最外层的运算符决定。例如,算术运算符(“+”,“*”,“%”)总是返回数字结果。字符串连接运算符(“||”)返回文本结果。等等。如果您对表达式的数据类型有疑问,可以使用特殊的 typeof() SQL 函数来确定数据类型是什么。例如:

代码语言:javascript
复制
sqlite> SELECT typeof('abc'+123);
numeric
sqlite> SELECT typeof('abc'||123);
text

对于表列,数据类型由 CREATE TABLE 语句的类型声明确定。当且仅当类型声明包含一个或多个以下字符串时,数据类型为 text:

BLOB CHAR CLOB TEXT

当然,在类型声明中搜索这些字符串不区分大小写。如果上述任何字符串都出现在类型声明的任何位置,那么该列的数据类型是文本。请注意,类型“VARCHAR”包含“CHAR”作为子字符串,因此它被视为文本。

如果上述字符串中没有一个出现在类型声明的任何位置,那么数据类型是数字类型。请特别注意,具有空类型声明的列的数据类型是数字。

5.0 示例

考虑以下两个命令序列:

代码语言:javascript
复制
CREATE TABLE t1(a INTEGER UNIQUE);        CREATE TABLE t2(b TEXT UNIQUE);
INSERT INTO t1 VALUES('0');               INSERT INTO t2 VALUES(0);
INSERT INTO t1 VALUES('0.0');             INSERT INTO t2 VALUES(0.0);

在左侧的序列中,第二个插入将失败。在这种情况下,字符串'0'和'0.0'被视为数字,因为它们被插入到数字列中,但是0 == 0.0违反了唯一性约束。但是,右侧序列中的第二个插入是有效的。在这种情况下,常量0和0.0被视为一个字符串,这意味着它们是不同的。

为了比较,SQLite 总是将数字转换为双精度(64位)浮点数。这意味着只有在无意义的数字中有所不同的长数字序列才会在数字列中相等,但如果它们在文本列中则会比较不相等。我们有:

代码语言:javascript
复制
INSERT INTO t1                            INSERT INTO t2
   VALUES('12345678901234567890');           VALUES(12345678901234567890);
INSERT INTO t1                            INSERT INTO t2
   VALUES('12345678901234567891');           VALUES(12345678901234567891);

如前所述,左边的第二个插入将失败,因为比较会先将两个字符串转换为浮点数,并且字符串中的唯一区别在于第20个数字中超过64位浮点数的分辨率。相反,右边的第二个插入将起作用,因为在这种情况下,插入的数字是字符串,并使用 memcmp()进行比较。

数字和文本类型对 DISTINCT 关键字也有所不同:

代码语言:javascript
复制
CREATE TABLE t3(a INTEGER);               CREATE TABLE t4(b TEXT);
INSERT INTO t3 VALUES('0');               INSERT INTO t4 VALUES(0);
INSERT INTO t3 VALUES('0.0');             INSERT INTO t4 VALUES(0.0);
SELECT DISTINCT * FROM t3;                SELECT DISTINCT * FROM t4;

左边的 SELECT 语句返回一行,因为'0'和'0.0'被视为数字,因此不清楚。但是右边的 SELECT 语句返回两行,因为0和0.0被视为不同的字符串。

代码语言:txt
复制
 SQLite is in the Public Domain.

扫码关注腾讯云开发者

领取腾讯云代金券