Manngo Asked: 2018-04-07 01:35:18 +0800 CST2018-04-07 01:35:18 +0800 CST 2018-04-07 01:35:18 +0800 CST SQLite:指定数据类型有什么用? 772 据我所知,SQLite 不强制定义表数据类型——它具有动态类型。例如,它允许您将字符串插入数字字段,或超过字符串的长度。 如果是这样,那么在CREATE TABLE语句中定义数据类型的意义何在? sqlite datatypes 3 个回答 Voted screwtop 2018-11-11T22:10:00+08:002018-11-11T22:10:00+08:00 除了 Vérace 的回答: 虽然 SQLite 不强制将存储类作为数据类型,但您可以typeof()在约束中应用更严格的类型检查,例如 Some_Quantity real check (typeof(Some_Quantity) = 'real') 您确实会丢失自动类型强制,例如它会阻止值'1'或1存储在真实列中(您必须将其指定为1.0)。但是,您可以允许多种类型: Some_Quantity real check (typeof(Some_Quantity) in ('real', 'integer', 'null') SQLite 的类型灵活性对于允许“带外”指标值也很方便,否则这些指标值对列的类型无效: Year check (typeof(Year) = 'integer' or Year in ('illegible', 'not disclosed')) Timmmm 2020-11-13T03:23:18+08:002020-11-13T03:23:18+08:00 SQLite 忽略列类型的可疑决定(他们称其为“功能”!)确实使指定它们变得毫无意义,但仍有一些理由这样做: 文档——至少你知道类型应该是什么,即使它根本没有被强制执行。 工具支持——可以通过编程方式读取列类型,如果知道类型,工具(例如 SQLiteStudio)会更有帮助。 与其他数据库的互操作性——SQL 并不是真正的标准,我认为大多数查询只能在一个数据库上运行,但是如果您将架构移植到其他数据库,那么如果您指定了类型,那么工作量就会少很多。 如果你不在乎这些,那根本就没有意义。您可以使用CHECK约束来强制执行类型,但这与实际的列类型无关,因此与这个问题并不真正相关。 Best Answer Vérace 2018-04-07T02:40:13+08:002018-04-07T02:40:13+08:00 SQLite 中有几个定义数据类型的基本原理,或者 SQLite 称之为“存储类”。 如果您阅读此页面,它将深入了解 SQLite 数据类型的功能和背后的推理。特别是,该页面的以下部分很有趣。 然而,SQLite 中的动态类型允许它完成传统刚性类型数据库中不可能完成的事情。 即像 C 编程语言一样,SQLite 允许您做非常愚蠢的事情,因为它还允许您做非常聪明的事情 - 例如,将 C 与 Java 和 SQLite 与其他 RDBMS 进行比较。 和: 存储类比数据类型更通用。 另一个原因: 在 SQLite 中,值的数据类型与值本身相关联,而不是与其容器相关联。SQLite 的动态类型系统向后兼容其他数据库引擎的更常见的静态类型系统,因为在静态类型数据库上工作的 SQL 语句应该在 SQLite 中以相同的方式工作。 还: 所以在大多数情况下,“存储类”与“数据类型”没有区别,这两个术语可以互换使用。 注意“在大多数情况下......” 为了最大限度地提高 SQLite 和其他数据库引擎之间的兼容性,并使上面的示例能够像在其他 SQL 数据库引擎上一样在 SQLite 上工作,SQLite 支持列上的“类型亲和性”概念。列的类型亲和性是存储在该列中的数据的推荐类型。这里的重要思想是该类型是推荐的,而不是必需的。 因此,这种通用性的一个很好的理由是与市场上几乎所有引擎的向后兼容性 - 默认不适合您,您可以自由更改代码(公共域许可证)。SQLite 是世界上最受欢迎的 RDBMS 的另一个原因! 还有一个有趣的花絮: 具有 REAL 亲和性的列的行为类似于具有 NUMERIC 亲和性的列,不同之处在于它将整数值强制转换为浮点表示。(作为内部优化,没有小数部分并存储在具有 REAL 亲和性的列中的小浮点值以整数形式写入磁盘以占用更少的空间,并在读出值时自动转换回浮点数。这优化在 SQL 级别是完全不可见的,只能通过检查数据库文件的原始位来检测。) 因此,具有 REAL 亲和性的列(与 INTEGER 相对)实际上确实对查询和/或计算的结果产生了功能差异。例如,字符串 '456.567'(SQLite 将BLOB 和数字存储为二进制,就像所有其他 SQL 数据库引擎一样)在 NUMERIC 计算中将被视为 456.567,但不会尝试强制 '6&%$$$#3'任何类型的数字。 SQLite 做出的一个重要假设是程序员为王,而不是引擎!如果出于某种原因,您想将 '6&%$$$#3' 转换为 INTEGER,那么您可以编写自己的算法,但 SQLite假设如果您希望处理 '6&%$$$# 3' 作为 INTEGER,那么你一定有充分的理由做出这样的选择! 一个简洁的说法是 SQLite 为您提供了非常强大的工具,但就像任何强大的工具一样,您必须谨慎和克制。基本上,SQLite 说“你是一个成年人——如果你想用我给你的钉枪射中自己的头部,那就去吧,但如果你受伤了,不要怪我!”。 除了 SQLite 页面,这些链接也很有帮助(1、2)。
除了 Vérace 的回答:
虽然 SQLite 不强制将存储类作为数据类型,但您可以
typeof()
在约束中应用更严格的类型检查,例如您确实会丢失自动类型强制,例如它会阻止值
'1'
或1
存储在真实列中(您必须将其指定为1.0
)。但是,您可以允许多种类型:SQLite 的类型灵活性对于允许“带外”指标值也很方便,否则这些指标值对列的类型无效:
SQLite 忽略列类型的可疑决定(他们称其为“功能”!)确实使指定它们变得毫无意义,但仍有一些理由这样做:
如果你不在乎这些,那根本就没有意义。您可以使用
CHECK
约束来强制执行类型,但这与实际的列类型无关,因此与这个问题并不真正相关。SQLite 中有几个定义数据类型的基本原理,或者 SQLite 称之为“存储类”。
如果您阅读此页面,它将深入了解 SQLite 数据类型的功能和背后的推理。特别是,该页面的以下部分很有趣。
即像 C 编程语言一样,SQLite 允许您做非常愚蠢的事情,因为它还允许您做非常聪明的事情 - 例如,将 C 与 Java 和 SQLite 与其他 RDBMS 进行比较。
和:
另一个原因:
还:
注意“在大多数情况下......”
因此,这种通用性的一个很好的理由是与市场上几乎所有引擎的向后兼容性 - 默认不适合您,您可以自由更改代码(公共域许可证)。SQLite 是世界上最受欢迎的 RDBMS 的另一个原因!
还有一个有趣的花絮:
因此,具有 REAL 亲和性的列(与 INTEGER 相对)实际上确实对查询和/或计算的结果产生了功能差异。例如,字符串 '456.567'(SQLite 将BLOB 和数字存储为二进制,就像所有其他 SQL 数据库引擎一样)在 NUMERIC 计算中将被视为 456.567,但不会尝试强制 '6&%$$$#3'任何类型的数字。
SQLite 做出的一个重要假设是程序员为王,而不是引擎!如果出于某种原因,您想将 '6&%$$$#3' 转换为 INTEGER,那么您可以编写自己的算法,但 SQLite假设如果您希望处理 '6&%$$$# 3' 作为 INTEGER,那么你一定有充分的理由做出这样的选择!
一个简洁的说法是 SQLite 为您提供了非常强大的工具,但就像任何强大的工具一样,您必须谨慎和克制。基本上,SQLite 说“你是一个成年人——如果你想用我给你的钉枪射中自己的头部,那就去吧,但如果你受伤了,不要怪我!”。
除了 SQLite 页面,这些链接也很有帮助(1、2)。