在我们的一个 SQL 表中,我们有一个真实的字段。实场精度为 7。我们需要在应用程序中提高精度。所以我们决定将我们的实数字段转换为十进制字段。
由于我们的表非常大,而且我们无法关闭事务日志,因此我们决定采用以下方法。
- 将 real 列重命名为 real_value_old(以前的名称是 real_value)
- 创建名称为 real_value 且数据类型为 decimal(38, 8)
- 将值从 real_value_old 批量复制到 real_value
我们在使用这种方法时遇到了一些问题。 例如,如果 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)
最佳答案
下面的链接将提供获取 float 据类型的位数的功能
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))
关于sql - 将值从实数值列复制到 SQL 中的小数值列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25130867/