在我们的一个SQL表中,我们有一个真实的字段。实际精度为7.我们的应用需要更高的精度。所以我们决定将真实字段转换为十进制字段。
由于我们的表非常大,而且因为我们无法关闭事务日志,所以我们决定使用以下方法。
我们正面临着这种方法的一些问题。 例如,如果real_value_old为545370.2,则real_value设置为545370.18750000
当我们检查问题时,我们认为是因为以下问题
update table set real_value = cast (real_value_old as decimal(38,8)) where some_condition
update table set real_value = ROUND(cast (real_value_old as decimal(38,8)), 8) where some_condition
update table set real_value = convert (decimal(38,8), real_value_old, 38) where some_condition
update table set real_value = real_value_old where some_condition
在以上所有情况中, 如果real_value_old为545370.2,则real_value设置为545370.18750000
有人可以在这提供解决方案吗?
此代码可以快速准确显示问题所在。在sql server 2012上确认
DECLARE @real REAL = 545370.2
SELECT cast(@real AS DECIMAL(38, 8))
,ROUND(cast(@real AS DECIMAL(38, 8)), 8)
,convert(DECIMAL(38, 8), @real, 38)
答案 0 :(得分:1)
以下链接将给出函数以获取浮点数据类型的位数
How to get the count of digits after the decimal point in a float column in ms sql?
修改该函数以在函数参数中使用REAL 然后,下面的SQL将工作
update table set real_value = ROUND(CAST (real_value_old AS decimal (38,8)), dbo.countDigits(real_value_old)) where some_condition
完整代码如下:
CREATE FUNCTION dbo.countDigits(@A real) RETURNS tinyint AS
BEGIN
declare @R tinyint
IF @A IS NULL
RETURN NULL
set @R = 0
while @A - str(@A, 18 + @R, @r) <> 0
begin
SET @R = @R + 1
end
RETURN @R
END
GO
DECLARE @real REAL = 545370.2
SELECT ROUND( cast(@real AS DECIMAL(38, 8)), dbo.countDigits(@real))
答案 1 :(得分:0)
MSDN文档中REAL数据类型的定义:
用于浮点数字数据的近似数字数据类型。浮点数据是近似值;因此,并非数据类型范围中的所有值都可以准确表示。 real的ISO同义词是float(24)。
这个例子展示了这在现实世界中是如何运作的(双关语)
DECLARE @real REAL = 545370.2
SELECT cast(@real AS DECIMAL(38, 8))
,ROUND(cast(@real AS DECIMAL(38, 8)), 8)
,convert(DECIMAL(38, 8), @real, 38)
每个结果都在545370.18750000
DECLARE @float float(24) = 545370.2
SELECT cast(@float AS DECIMAL(38, 8))
,ROUND(cast(@float AS DECIMAL(38, 8)), 8)
,convert(DECIMAL(38, 8), @float, 38)
与第一个块相同
DECLARE @doublefloat float(53) = 545370.2
SELECT cast(@doublefloat AS DECIMAL(38, 8))
,ROUND(cast(@doublefloat AS DECIMAL(38, 8)), 8)
,convert(DECIMAL(38, 8), @doublefloat, 38)
双精度浮点数正确:545370.20000000
所以你去吧。当结果不允许进行近似并且研究您的数据类型以避免头痛时,不要使用近似数字;)
修改强> 示例中给出的具体数字可以这样处理:
DECLARE @float real = 545370.2
SELECT CEILING(@float*10)/10
根据您所处理的数字范围,您可以使用适用于整个范围的CEILING / FLOOR / ROUND来查看公式。