Microsoft SQL 服务器:数字常量精度

Microsoft SQL Server : numeric constants precision

我对这个结果不够精确感到困惑:

select convert(numeric(11, 10), 1 / 3.0)

   0.3333330000

为什么我要十位却只有六位小数?这里我写了3.0而不是3来强制浮点除法而不是整数除法(1/3的值为零)。

但是那个常量是什么类型3.0?它似乎不是任何本机 SQL 服务器浮点类型,它们都给出不同的结果:

select convert(numeric(11, 10), 1 / convert(real, 3))

   0.3333333433

select convert(numeric(11, 10), 1 / convert(double precision, 3))

   0.3333333333

select convert(numeric(11, 10), 1 / convert(float, 3))

   0.3333333333

直到现在,我一直尝试编写 3.0 来获取浮点常量,就像在 C 等编程语言中会发生的那样。但这不是 SQL 中的解释。发生什么事了?

答案是3.0给出的不是浮点型常量,而是数值型常量,具体是numeric(2,1)。您可以使用以下方式查看:

select sql_variant_property(3.0, 'basetype') as b,
       sql_variant_property(3.0, 'precision') as p,
       sql_variant_property(3.0, 'scale') as s
b: numeric
p: 2
s: 1

如果您明确指定此类型,您会得到相同的奇数有限精度结果:

select convert(numeric(11, 10), 1 / convert(numeric(2, 1), 3))
   0.3333330000

仍然很奇怪 -- 当原始数字常量只有一位而输出类型需要十位时,我们怎么会得到六位小数?根据数值类型提升的规则我们可以看到除法表达式得到类型 numeric(8, 6):

select sql_variant_property(1 / convert(numeric(2, 1), 3), 'basetype') as b,
       sql_variant_property(1 / convert(numeric(2, 1), 3), 'precision') as p,
       sql_variant_property(1 / convert(numeric(2, 1), 3), 'scale') as s
b: numeric
p: 8
s: 6

为什么恰恰是某物与一的倒数 d.p。应该得到六个 d.p,而不是五个或七个,我不清楚,但我想 SQL 必须选择一些东西。

故事的寓意是不要在 SQL 中编写像 1.0 这样的数字常量,以期获得浮点语义。您将获得数字语义,但小数位可能太少而无用。如果你想要浮点数,写convert(1, float)1e,或者使用数字类型并检查每一步计算是否有d.p的数量。你要

感谢向我指出 https://bertwagner.com/posts/data-type-precedence-and-implicit-conversions/ 的同事,其中解释了其中的一些内容。