相关SQLite数据类型(例如INT,INTEGER,SMALLINT和TINYINT)之间有什么区别?


101

在SQLite3中创建表时,遇到所有暗示相似内容的数据类型时,我会感到困惑,所以有人能告诉我以下数据类型之间的区别吗?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

是否有一些文档列出了最小/最大。各种数据类型的容量?例如,我猜smallint它的最大值大于tinyint,但值小于整数,但是我不知道这些容量是多少。

Answers:


95

SQLite,从技术上讲,它没有数据类型,清单类型系统中有存储类,是的,如果您习惯于传统RDBMSes ,这会令人困惑。内部的所有内容都存储为文本。根据关联性(分配给列的ala数据类型),将数据类型强制/转换为各种存储位置。

我建议您做的最好的事情是:

  1. 暂时忘记您曾经了解的有关独立数据库数据类型的所有信息

  2. SQLite网站上阅读以上链接。

  3. 从旧模式中获取类型,然后查看它们要映射到的内容 SQLite

  4. 将所有数据迁移到SQLite数据库。

注意:数据类型的限制可能很麻烦,尤其是如果您在中添加了持续时间或日期或类似性质的内容时SQLSQLite几乎没有内置函数可用于此类操作。但是,SQLite确实为您提供了一种简单的方法,使您可以通过sqlite3_create_function库函数制作自己的内置函数来添加持续时间和类似性质的内容。您将使用该功能代替传统的存储过程。


1
感谢您的答复和链接。这是否意味着我应该坚持文本的基本类型,数字,整数,实数,无?似乎对我来说非常有限,尤其是来自MSSQL,Foxpro和Oracle的背景。问候。
艾伦·哈里斯

6
我同意你的观点,但乍一看似乎很有限。但是,我认为您会发现SQLite在如何通过其相似性系统将数据放入数据库中非常宽容。SQLite不是独立的-它被设计为一个小型数据库后端,您将其放置在小型应用程序中,只能通过代码中的数据库访问API进行访问。在SQLite中解决问题通常是弄清楚他们希望您如何做。
J. Polfer

我会坚持使用基本类型。
J. Polfer

4
@Alan:将数字相似性列声明为DATE或可能会很有用BOOLEAN,但是我不会费心区分不同大小的整数。对于的情况尤其如此,在这种情况INTEGER PRIMARY KEY下,确切的类型名称很重要。
dan04'5

根据sqlite.org/fileformat.html,“一切都存储为文本”似乎是错误的,它表示数字存储为紧凑型varints / float64,而只有blob和文本存储为字符串
phiresky,

47

区别在于语法糖。就类型相似性而言,类型名称中只有几个子字符串很重要。

  • INT,INTEGER,SMALLINT,TINYINT→INTEGER关联,因为它们都包含“ INT”。
  • LONGCHAR,LONGVARCHAR→TEXT关联,因为它们包含“ CHAR”。
  • DEC,DECIMAL,DATETIME,SMALLDATETIME→NUMERIC,因为它们不包含任何重要的子字符串。

SQLite网站上列出了用于确定亲和力的规则。

如果您坚持严格输入,则可以使用CHECK约束来实现:

CREATE TABLE T (
   N   INTEGER CHECK(TYPEOF(N) = 'integer'),
   Str TEXT CHECK(TYPEOF(Str) = 'text'),
   Dt  DATETIME CHECK(JULIANDAY(Dt) IS NOT NULL)
);

但是我从来没有理会它。

至于每种类型的容量:

  • INTEGER始终签名为64位。请注意,SQLite在后台优化了小整数的存储,因此,TINYINT仍然无济于事。
  • REAL始终为64位(double)。
  • TEXT并且BLOB具有由预处理程序宏确定的最大大小,默认大小为1,000,000,000字节。

1
好招 请注意,这种方法确实需要插入/更新一个值,以使其具有与中相同的存储类TYPEOF。因此,尝试插入将由SQlite转换为NUMERIC / INTEGER存储类的TEXT的尝试(即,按照sqlite.org/datatype3.html#affinity进行的这种转换是无损的)会失败。换句话说,这种方法比插入值然后通过某种方式神奇地验证SQLite用来存储该值的存储类的临时方法更为严格。有关更宽松的方法,请参见下面的答案。
eold 2015年

10

其中大多数都是为了兼容性。您实际上只有整数,浮点数,文本和斑点。日期可以存储为数字(unix时间为整数,microsoft time为浮点数)或文本。


我已经将其用于基于Web的项目,无论如何最终最终所有内容都是文本,都被放置到html页面中。我省去了很多数据转换,并且大多数列只使用了文本。效果很好。
杰伊,2010年

3

NULL。该值为NULL值。

INTEGER。该值是一个有符号整数,根据值的大小存储在1、2、3、4、6或8个字节中。

REAL。该值是一个浮点值,存储为8字节IEEE浮点数。

TEXT。该值是一个文本字符串,使用数据库编码(UTF-8,UTF-16BE或UTF-16LE)存储。

BLOB。该值是数据的一滴,完全按输入存储。


1

作为对dan04的补充,如果您想盲目插入a NUMERIC代表的非零值,TEXT但要确保文本可转换为数字:

your_numeric_col NUMERIC CHECK(abs(your_numeric_col) <> 0)

典型的用例是在来自程序的查询中,该程序将所有数据都视为文本(为了统一和简单起见,因为SQLite已经这样做了)。这样做的好处是它允许这样的构造:

INSERT INTO table (..., your_numeric_column, ...) VALUES (..., some_string, ...)

如果您使用占位符,这非常方便,因为您不必专门处理此类非零数字字段。使用Python sqlite3模块的示例是,

conn_or_cursor.execute(
    "INSERT INTO table VALUES (" + ",".join("?" * num_values) + ")",   
    str_value_tuple)  # no need to convert some from str to int/float

在上面的示例中,in中的所有值在str_value_tuple传递给SQlite时都将转义并引用为字符串。但是,由于我们不是通过显式检查类型,TYPEOF而仅是对type的可转换性,所以它仍将按需运行(即,SQLite会将其存储为数字,否则将失败)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.