我有一个10M行以上的表,希望将其中一列的数据类型从nvarchar(254)
更改为decimal(7,2)
。进行此更改的最高效、最有效的查询是什么?
我已经尝试使用ALTER来进行此更改,但在SSMS 中出现错误
将数据类型nvarchar转换为数字时出错。
我也尝试过使用CAST,但这也会导致错误。诚然,我不是DBA,所以我很难理解以下内容:
-
如何正确编写不产生错误的CAST查询
-
CAST和CONVERT函数是否在数据库级别更改数据的设计(即在对象资源管理器中,当我右键单击表,然后单击"设计"时,我会看到列的数据类型已更改),或者更改是否只持续到运行下一个查询或退出程序。
此表最初是在一个多月前创建的,是几个月前运行的工作流的结果;此后,该工作流被安排以每小时一次的节奏将新数据推送到表中,因此删除作业/表并重新开始不是一种选择。
SET STATISTICS TIME ON
ALTER TABLE Clone3
ALTER COLUMN Price decimal(7,2)
最终目标是正确存储这些数据,以便在将其纳入其他可视化程序(例如Tableau、Power BI等)时可以执行算术运算。也就是说,这里的预期结果是将数据类型更改为Decimal(7,2)
,但实际结果是nvarchar(254)
。
更新
在运行SELECT Price from Clone3 WHERE TRY_CONVERT(decimal(7,2),Price) IS NULL
之后,有239条记录以科学记数法返回。例如-5.000000000003E-2
最终更新
我运行以下查询来更新导致转换错误的记录(这些是负数,如"-0.05",由于某种奇怪的原因被转换为科学记数法)。
UPDATE Clone3
SET Price = CAST(Price AS Float)
WHERE TRY_CONVERT(decimal(7,2), Price) IS NULL
因为所有记录现在都是数字数据类型,所以我可以使用此查询将整个数据集转换为十进制(7,2)。
ALTER TABLE Clone3
ALTER COLUMN Price decimal(7,2)
我想我可以说这已经解决了,非常感谢大家的回复,尤其是@Larnu的代码片段,它最终帮助我解决了这个问题。
这个5.9999999999999998E-2
不能直接转换为十进制(7,2),尽管它可以转换为float
,然后可以转换为十进制。例如
select cast(cast('5.9999999999999998E-2' as float) as decimal(7,2))
虽然不是最有效的,也不是这类事情的通用解决方案,但你可以更改两次表格,例如:
use tempdb
drop table if exists t
create table t(s varchar(200))
insert into t(s) values ('5.9999999999999998E-2')
go
alter table t alter column s float
alter table t alter column s decimal(7,2)
go
select * from t
最有效的方法可能是清空表并重新加载:
select *
into temp_t
from t;
truncate table temp_t;
alter table t alter column price decimal(7, 2);
insert into t
select *
from temp_t;
更新现有记录会带来更多的开销。