当我从 VARCHAR(MAX) 转换为 Numeric(P,S) 时,为什么 SQL 服务器会覆盖我的比例值?
Why does SQL Server override my scale value when I am casting from VARCHAR(MAX) to Numeric(P,S)?
我想了解为什么 SQL 服务器在我将值从 VARCHAR(MAX)
转换为 NUMERIC(P,S)
时修改我的标度值。
示例如下:
--declare @val1 as numeric (18,6)
--declare @val2 as numeric (18,6)
DECLARE @val1 AS VARCHAR(MAX)
DECLARE @val2 AS VARCHAR(MAX)
SET @val1 = '2383.4912500000'
SET @val2 = '2383.4912000000'
DROP TABLE IF EXISTS TMP
SELECT
V1 = @VAL1,
VC1 = CAST(@VAL1 AS NUMERIC(30, 20)),
valDiff = ABS(CAST(CAST(@VAL2 AS NUMERIC(18, 6)) - CAST(@VAL1 AS NUMERIC(18, 6)) AS NUMERIC(30, 20)) / @VAL1)
INTO
TMP
SELECT * FROM TMP
-- when variable is VARCHAR(MAX), valDiff == 0.00000002 which is correct, but rounded.
-- when the variable is NUMERIC(18, 6), valDiff == 0.0000000209776310275945 which is correct and not rounded
当您从精度非常高的小数开始时,算术运算的结果可能会缩小其小数位数以保留更多有效数字。如果值 没有 30 non-zero 小数点左边的数字并不重要。转换基于声明的精度和小数位数:
这里您的 varchar
正在以过高的精度隐式转换为小数。
由于需要小心地将中间结果转换为小数,使用 float
执行所有计算通常更容易,它在所有尺度上保持约 15 位有效数字的精度,并且只转换最终结果到 decimal
进行存储。例如
declare @val1 as float ='2383.4912500000'
declare @val2 as float ='2383.4912000000'
select cast( abs(@VAL2 - @VAL1) / @VAL1 as numeric(30,20) )
我想了解为什么 SQL 服务器在我将值从 VARCHAR(MAX)
转换为 NUMERIC(P,S)
时修改我的标度值。
示例如下:
--declare @val1 as numeric (18,6)
--declare @val2 as numeric (18,6)
DECLARE @val1 AS VARCHAR(MAX)
DECLARE @val2 AS VARCHAR(MAX)
SET @val1 = '2383.4912500000'
SET @val2 = '2383.4912000000'
DROP TABLE IF EXISTS TMP
SELECT
V1 = @VAL1,
VC1 = CAST(@VAL1 AS NUMERIC(30, 20)),
valDiff = ABS(CAST(CAST(@VAL2 AS NUMERIC(18, 6)) - CAST(@VAL1 AS NUMERIC(18, 6)) AS NUMERIC(30, 20)) / @VAL1)
INTO
TMP
SELECT * FROM TMP
-- when variable is VARCHAR(MAX), valDiff == 0.00000002 which is correct, but rounded.
-- when the variable is NUMERIC(18, 6), valDiff == 0.0000000209776310275945 which is correct and not rounded
当您从精度非常高的小数开始时,算术运算的结果可能会缩小其小数位数以保留更多有效数字。如果值 没有 30 non-zero 小数点左边的数字并不重要。转换基于声明的精度和小数位数:
这里您的 varchar
正在以过高的精度隐式转换为小数。
由于需要小心地将中间结果转换为小数,使用 float
执行所有计算通常更容易,它在所有尺度上保持约 15 位有效数字的精度,并且只转换最终结果到 decimal
进行存储。例如
declare @val1 as float ='2383.4912500000'
declare @val2 as float ='2383.4912000000'
select cast( abs(@VAL2 - @VAL1) / @VAL1 as numeric(30,20) )