CREATE TABLE [dbo].[TES_Tracks](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Rate] [float] NULL,
[TOL] [datetime] NOT NULL
)
我希望将汇率列更改为decimal(28,6)。该表中已经有了很多以浮点格式存储的数据,我担心会有数据丢失。我该如何操作?
CREATE TABLE [dbo].[TES_Tracks](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Rate] [float] NULL,
[TOL] [datetime] NOT NULL
)
我希望将汇率列更改为decimal(28,6)。该表中已经有了很多以浮点格式存储的数据,我担心会有数据丢失。我该如何操作?
未经测试,但这也许值得一试...
ALTER TABLE [dbo].[TES_Tracks] ADD [RateNew] DECIMAL(28,6);
UPDATE [dbo].[TES_Tracks] set RateNew = Cast(Rate as Decimal(28,6));
由于SQL Server可以隐式地处理十进制数和浮点数,因此如果您存在数据损失,这将为您获取行。
Select * From [dbo].[TES_Tracks] where Rate <> RateNew;
那么,如果您对我们的服务感到满意......
ALTER TABLE [dbo].[TES_Tracks] DROP COLUMN [Rate];
然后将RateNew列重命名为Rate
EXEC sp_RENAME 'TES_Tracks.RateNew' , 'Rate', 'COLUMN'
SELECT
[Rate],
CAST([Rate] as decimal(28, 6)) Rate_decimal
FROM [dbo].[TES_Tracks]
WHERE [Rate] - FLOOR([Rate]) < 0.000001;
一旦您确认 CAST 表达式正确无误,就可以使用 UPDATE 语句应用它。同样地,您只能更新那些具有 [Rate] - FLOOR([Rate])
的行,从而获得良好的性能。
UPDATE [dbo].[TES_Tracks]
SET [Rate] = CAST([Rate] as decimal(28, 6))
WHERE [Rate] - FLOOR([Rate]) < 0.000001;
ALTER TABLE [dbo].[TES_Tracks] ALTER COLUMN [Rate] DECIMAL(28,6);
[Rate] - FLOOR([Rate])
。 - CoderKKupdate
语句中的cast
语句将会舍去你的浮点数非常小的小数部分,但当系统试图将这个截断的十进制值持久化回你的列时,它将会隐式地再次转换为浮点数 - 没有保证你生成的十进制数可以映射到一个浮点数中而不引入另一个小的小数部分。换句话说,update
步骤不仅是无用的,而且可能实际上更新数据值为新的值。 - youcantryreachingmewhere
子句应该查看差异的绝对值。有可能您的浮点数的小数部分恰好低于一个精确的十进制值。您的 select
背后的概念是正确的 - 但我怀疑您在查看仅有6位小数时实际上不会看到任何值的差异。相反,看一下新的十进制值和原始浮点数之间的差异可能更有意义。最终,alter
语句是要采取的方法,但这里的说明并没有真正解决如何确信哪些数据会丢失的问题。 - youcantryreachingme
ALTER TABLE [dbo].[TES_Tracks] ALTER COLUMN [Rate] DECIMAL(28,6)
- Lamak