【问题标题】: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 亿行表的系统上工作,我可能会注意浪费的存储空间。我可能会注意索引页面大小和索引扫描性能。在这种情况下,我不想浪费空间。

标签: sql sql-server sqldatatypes unsigned-integer


【解决方案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 数据类型。

      【讨论】:

        猜你喜欢
        • 2018-10-17
        • 1970-01-01
        • 1970-01-01
        • 2011-11-08
        • 1970-01-01
        • 2018-04-02
        • 2020-06-08
        • 2015-11-23
        • 2013-01-18
        相关资源
        最近更新 更多