如果我在 SSMS 中执行,则遵循批处理语句,给我如下所示的结果
DECLARE @M_TUBE_VOLUME NUMERIC(38,10),
@M_TUBE_OD NUMERIC(38,10)=12.50000,
@M_TUBE_ID NUMERIC(38,10)=12.50000,
@M_TUBE_LEN NUMERIC(38,10)=4000.00000,
@M_TUBE_COUNT NUMERIC(38,10)=212.4215000,
@M_S_TUBE_LEN NUMERIC(38,10)=0.0000,
@M_S_TUBE_COUNT NUMERIC(38,10)=3587.000
SET @M_TUBE_VOLUME=(SELECT 3.141592 / 4 * @M_TUBE_OD * @M_TUBE_ID * ((@M_TUBE_LEN * @M_TUBE_COUNT) + (@M_S_TUBE_LEN * @M_S_TUBE_COUNT)));
SELECT @M_TUBE_VOLUME
RESULT -- 104272138.7104680000
如果我使用 select 语句在 SSMS 中执行同样的事情
SELECT 3.141592 / 4 * 12.50000 * 12.50000 * ((4000.00000 * 212.4215000) + (0.0000 * 3587.000))
RESULT -- 104272138.285625000000000000000
为什么两个结果不同,请帮助我
它与舍入有关。由于您的计算涉及带有小数位的数字。
请参阅文档精度、小数位数和长度 (Transact-SQL(
我在这里提取了相关部分
Operation Result precision Result scale * e1 * e2 p1 + p2 + 1 s1 + s2 e1 / e2 p1 - s1 + s2 + max(6, s1 + p2 + 1) max(6, s1 + p2 + 1)
- 结果精度和小数位数的绝对最大值为 38。当结果精度大于 38 时,它将降低到 38,并且 相应的比例减小,以防止截断 结果的组成部分。在某些情况下,例如乘法或 除法,比例因子不会降低,以保持小数 精度,尽管可以提高溢出误差。
在第二个查询中,像3.141592
这样的数字是numeric(7,6)
,12.50000
是numeric(7,5)
,在第一个查询中,所有这些都是numeric(38,10)
舍入发生在前 4 个表达式上。
我使用SELECT INTO
临时表,然后查询临时表中列的数据类型
SELECT f1 = 3.141592 / 4 * @M_TUBE_OD * @M_TUBE_OD,
f2 = 3.141592 / 4 * 12.50000 * 12.50000
INTO #t
select c.name, t.name, c.precision, c.scale
from tempdb.sys.columns c
inner join master.sys.systypes t on c.system_type_id = t.xtype
where object_id = object_id('tempdb..#t')
name name percision scale
f1 numeric 38 6
f2 numeric 25 18
您可以看到,对于您的第一个查询,结果scale
减少到仅6
。因此,对于第一个查询,前 4 个表达式的结果是122.718438
(舍入为38
(而不是122.7184375
。
你过度定义了你的numeric
precision
。减少它并尝试
在第二个版本中,您尚未显式定义数据类型,并且默认为 FLOAT。
可以通过将查询更改为
DECLARE @M_TUBE_VOLUME FLOAT,
@M_TUBE_OD FLOAT=12.50000,
@M_TUBE_ID FLOAT=12.50000,
@M_TUBE_LEN FLOAT=4000.00000,
@M_TUBE_COUNT FLOAT=212.4215000,
@M_S_TUBE_LEN FLOAT=0.0000,
@M_S_TUBE_COUNT FLOAT=3587.000
SET @M_TUBE_VOLUME=(SELECT 3.141592 / 4 * @M_TUBE_OD * @M_TUBE_ID * ((@M_TUBE_LEN * @M_TUBE_COUNT) + (@M_S_TUBE_LEN * @M_S_TUBE_COUNT)));
SELECT @M_TUBE_VOLUME