据我所知,SQLite 不强制定义表数据类型——它具有动态类型。例如,它允许您将字符串插入到数字字段中,或超出字符串的长度。
如果是这样,那么在CREATE TABLE
语句中定义数据类型有什么意义?
小智 10
进一步 Vérace 的回答:
虽然 SQLite 不会将存储类强制为数据类型,但您可以typeof()
在约束中使用更严格的类型检查,例如
Some_Quantity real check (typeof(Some_Quantity) = 'real')
Run Code Online (Sandbox Code Playgroud)
您确实失去了自动类型强制,例如它会阻止值'1'
或1
存储在实际列中(您必须将其指定为1.0
)。但是,您可以允许多种类型:
Some_Quantity real check (typeof(Some_Quantity) in ('real', 'integer', 'null')
Run Code Online (Sandbox Code Playgroud)
SQLite 的类型灵活性对于允许“带外”指标值也很方便,否则这些值对列的类型无效:
Year check (typeof(Year) = 'integer' or Year in ('illegible', 'not disclosed'))
Run Code Online (Sandbox Code Playgroud)
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)的列实际上确实会对查询和/或计算的结果产生功能差异。例如,对于 NUMERIC 计算,字符串“456.567”(SQLite 将BLOB 和数字存储为二进制,就像其他 SQL 数据库引擎一样)将被视为 456.567,但不会尝试强制“6&%$$$#3”转换为任何类型的数字。
SQLite 做出的一个重要假设是程序员为王,而不是引擎!如果出于某种原因,您想将 '6&%$$$#3' 转换为 INTEGER,那么您可以编写自己的算法,但 SQLite假定如果您希望处理 '6&%$$$# 3' 作为一个 INTEGER,那么您必须有充分的理由做出这样的选择!
一种简洁的表达方式是,SQLite 为您提供了非常强大的工具,但像任何强大的工具一样,人们必须保持谨慎和克制。基本上,SQLite 说“你是一个成年人 - 如果你想用我给你的射钉枪向自己的头部开枪,那就尽管吧,但如果你受伤了,不要怪我!”。
除了 SQLite 页面之外,这些链接也很有帮助 ( 1 , 2 )。
归档时间: |
|
查看次数: |
2633 次 |
最近记录: |