为啥 SQL Server 不支持无符号数据类型?
Posted
技术标签:
【中文标题】为啥 SQL Server 不支持无符号数据类型?【英文标题】:Why doesn't SQL Server support unsigned datatype?为什么 SQL Server 不支持无符号数据类型? 【发布时间】:2011-05-26 00:24:00 【问题描述】:我正在特别考虑未签名的int
。
这是一个实际的例子:当你的身份列达到最大值时你会怎么做?可以使用BigInt
(8 字节存储而不是 4)或重构应用程序以支持负整数,甚至可以创建自己的规则,如this answer 所示;这些选项都不是最优的。
UInt
将是一个理想的解决方案,但 SQL Server 不提供它(而 mysql 提供)。
我知道无符号数据类型不是 SQL 标准 (SQL-2003) 的一部分,但对我来说仍然是一种浪费。
不包括这些的原因是什么(在 SQL Server 或标准中)?
【问题讨论】:
询问 SQL Server 设计团队.....另外:您是否真的会最大化甚至 2 BILLION INT IDENTITY 值? REALLY?!?!?! 如果您有超过 20 亿行正在处理的任何内容,我敢打赌,您可以腾出一些磁盘空间并使用 BIGINT 作为 IDENTITY...。 marc_s 是什么意思?这只是连续 50 年每 800 毫秒插入一次,你的表没有那种活动吗? :) @Mike M:并不是我们所有人都在开发米老鼠应用程序……我们在不到 2 年的时间里使用了 30 亿多个 bigint。峰值大于每秒 2000 行。 @gbn 我并不是要暗示没有人有这种负担。但是,如前所述,如果您每秒的行数超过 2000 行,那么额外的 2B 将无济于事。 @Mike M 和@marc_s,如果我在一个有 20 亿行表的系统上工作,我可能会注意浪费的存储空间。我可能会注意索引页面大小和索引扫描性能。在这种情况下,我不想浪费空间。 【参考方案1】:如果我不得不猜测,我会说他们试图避免类型的扩散。一般来说,无符号整数可以做任何有符号整数不能做的事情。至于您需要一个介于 2147483648 和 4294967296 之间的数字的情况,您可能应该使用 8 字节整数,因为该数字最终也会超过 4294967296。
【讨论】:
我想这是我们能得到的最接近这个问题的答案。谢谢。 如果“类型的增殖”可以节省一些空间/金钱,你为什么认为这可能是邪恶的。 按值获取行也会更慢(即ORDER BY ABS(Id)
),尤其是当列是聚集主键时。例如,使用 32 位 unix 时间戳通常是一种将标准 SQL 日期时间缩短 4 个字节的便捷方法。【参考方案2】:
为此,您可以使用 -2,147,483,648 作为种子值。
Identity(-2147483648, 1)
【讨论】:
哈,我非常喜欢这个答案。我不确定我是否曾经实现过它,但它确实解决了一半 id 未使用的问题。 好的解决方案...不是很好....但可以解决问题...使用 min_value 作为零 (0)...有效地使用开尔文标度 ;)【参考方案3】:我发现了一个类似的问题on Microsoft Office Dev Center.
Jim Hogg(项目经理)的回复对添加 unsigned int 有一些优点和缺点。主要缺点是实现隐式类型转换的规则变成了正确的噩梦。
请求以“无法修复”的形式关闭。
【讨论】:
该链接不再起作用,所以我无法阅读原始答案。但我相信问题不在于它是一场噩梦;就是没有一个标准来说明如何去做。例如,他们可以做 MySQL 所做的事情(我认为其他 DBMS 不支持 UNSIGNED),但如果另一个 DBMS 添加对符号的支持,他们可以使用不同的规则。转换设计是一个重要的问题。 javascript 就是一个例子,说明当它没有被认真对待时会发生什么。 更新链接 - Jim Hogg 对 MSSN Office 开发者论坛的评论。 我非常需要无符号整数类型,因为它们更准确地代表了要存储的数据的性质。我完全理解对隐式转换的担忧,但这不应该是一个问题,因为不应该允许从有符号类型进行隐式转换 to 任何无符号类型 - 这巧妙地解决了 那个 i> 问题(我假设 ISO SQL 需要它?)。归根结底,我的挫败感是,作为应用程序开发人员,我们被告知要对数据建模尽可能接近业务领域,但随后我们的工具阻碍了我们这样做。【参考方案4】:它们不支持 SIGNED 和 UNSIGNED 关键字,因为它们不是标准的。在 SQL 标准中,所有数字类型都是有符号的。
UNSIGNED(和 SIGNED,这是默认值)是 MySQL 扩展,可用于在相同的字节数中存储更高的无符号数,并且不允许负数。
【讨论】:
“在 SQL 标准中,所有数字类型都是有符号的” - 是的,但是 ISO SQL 与数据建模和应用程序的日常挑战痛苦地发展。为了发布可用的东西,违反 ISO SQL 规范是绝对必要的。 UNSIGNED 类型是可取的,但不是那么重要。大多数 DBMS 不支持它们,这使得类型转换(以及不同类型之间的操作)更加简单。如果要避免负数,请添加 CHECK 约束。【参考方案5】:以 32 位(8 字节)int 为例。 32 位 int 的范围是从 -2^31 到 2^31-1。 记录你分配的值需要 31 位,记录值的符号只需要 1 位。
所以你的问题的答案是“不必要的”。即使您分配的每个值都是正数,但每个值仅浪费 1 位。为每个值仅节省 1 位创建新数据类型并不是优化存储空间的好方法。
【讨论】:
【参考方案6】:将您的数据库设置为具有最小身份 身份(-2147483648, 1)
然后在加载到您的 .net UInt64 变量时添加 2147483648 到它。然后 -2147483648 变为 0 -1000000000 变为 1147483648
但在大多数情况下,内部密钥也不应该暴露给客户端,我通常使用单独的密钥,可以是“ABCKey1”之类的任何内容但是,我同意该数据类型在 99% 的系统中都足够大。如果您真的需要更多,您可以使用 GUID - 但是这对于 Index 来说很糟糕,除非您使用下一个连续的 GUID。
【讨论】:
【参考方案7】:在某些情况下,SQL Server 中需要无符号数。例如,可能需要将二进制值的等价物存储为整数。在这种情况下,对于 32 位二进制值,需要使用 64 位 bigint 而不是 32 位 int 数据类型。
【讨论】:
以上是关于为啥 SQL Server 不支持无符号数据类型?的主要内容,如果未能解决你的问题,请参考以下文章