Small. Fast. Reliable.
Choose any three.

Datatypes In SQLite Version 2

1.0   Typelessness

SQLite is "typeless". This means that you can store any kind of data you want in any column of any table, regardless of the declared datatype of that column. (See the one exception to this rule in section 2.0 below.) This behavior is a feature, not a bug. A database is supposed to store and retrieve data and it should not matter to the database what format that data is in. The strong typing system found in most other SQL engines and codified in the SQL language spec is a misfeature - it is an example of the implementation showing through into the interface. SQLite seeks to overcome this misfeature by allowing you to store any kind of data into any kind of column and by allowing flexibility in the specification of datatypes.

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

创建表ex1(a,b,c);

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

创建表ex2(
  VARCHAR(10),
  b NVARCHAR(15),
  c TEXT,
  d整数
  e FLOAT,
  f BOOLEAN,
  g CLOB,
  h BLOB,
  我时间戳
  j数值(10,5)
  k变化特征(24),
  l国家变更字符(16)
);

依此类推。基本上,任何名称序列(可选)后都可以在括号中加上一个或两个带符号的整数。

2.0整数主键

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是无类型的。但是,在对数据进行排序和比较时,一些类型的概念会起作用。为此,列或表达式可以是以下两种类型之一:numerictext。根据正在排序或比较的数据类型,排序或比较可能会得出不同的结果。

如果数据是文本类型的,则比较由标准C数据比较函数memcmp()strcmp()确定。比较将逐个查看来自两个输入的字节,然后返回第一个非零差异。字符串以'\ 000'结尾,因此,较短的字符串将排在较长的字符串之前,这与您期望的一样。

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

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

对于文本值和数字值,NULL都排在其他任何值之前。使用“ <”或“> =”之类的运算符将任何值与NULL进行比较始终为false。

4.0 SQLite如何确定数据类型

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

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

sqlite> SELECT typeof('abc'+ 123);
数字
sqlite> SELECT typeof('abc'|| 123);
文本

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

BLOB
CHAR
CLOB
TEXT

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

如果以上字符串均未出现在类型声明中的任何位置,则数据类型为数字。特别要注意的是,带有空类型声明的列的数据类型是数字。

5.0范例

请考虑以下两个命令序列:

创建表t1(整数);创建表t2(b文本唯一);
插入t1值('0'); 插入t2值(0);
插入t1值('0.0'); 插入t2值(0.0);

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

为了进行比较,SQLite始终将数字转换为双精度(64位)浮点数。这意味着如果数字列中只有一小部分数字不同的长数字序列将比较相等,而在文本列中则将比较不相等。我们有:

插入t1插入t2
   VALUES('12345678901234567890'); VALUES(12345678901234567890);
插入t1插入t2
   VALUES('12345678901234567891'); VALUES(12345678901234567891);

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

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

创建表t3(a整数); 创建表t4(b文本);
插入t3值('0'); 插入t4值(0);
插入t3值('0.0'); 插入t4值(0.0);
选择DISTINCT * FROM t3; 选择DISTINCT * FROM t4;

左侧的SELECT语句返回一行,因为'0'和'0.0'被视为数字,因此无法区分。但是右侧的SELECT语句返回两行,因为0和0.0被视为不同的字符串。