【问题标题】:How to convert nvarchar(254) to decimal(7,2)如何将 nvarchar(254) 转换为十进制(7,2)
【发布时间】:2019-01-21 18:54:21
【问题描述】:

我有一个包含 10M+ 行的表,并且想要将其中一列的数据类型从 nvarchar(254) 更改为 decimal(7,2)。进行此更改的最有效和最有效的查询是什么?

我曾尝试使用 ALTER 进行此更改,但在 SSMS 中出现错误

将数据类型 nvarchar 转换为数值时出错。

我也尝试过使用 CAST,但这也会导致错误。诚然,我不是 DBA,所以我很难理解以下内容:

  1. 如何正确编写不会产生错误的 CAST 查询

  2. 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.0000000000000003E-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 提供的代码 sn-p 最终帮助我解决了这个问题。

【问题讨论】:

  • 如果您收到有关转换的错误,您首先需要找到有问题的值。你能分享(部分)来自SELECT Price from Clone3 WHERE TRY_CONVERT(decimal(7,2),Price) IS NULL;的结果吗?谢谢。
  • 另外,我刚刚注意到了,但是你说的“数据类型要更改为Decimal(7,2),但实际结果是nvarchar(254)”是什么意思?如果您希望返回的结果为varchar,则存储varchar。不过老实说,这句话听起来像是XY Problem
  • @Larnu - 我在写这篇文章时尝试遵循提供的指导方针,并认为我误读了一些东西。我的场景中的“实际结果”是我目前看到的。重申我上面写的内容,“......这里的预期结果是将数据类型更改为 Decimal(7,2),但我目前看到的是 nvarchar(254)。”如有任何混淆,我们深表歉意。
  • @Larnu - 以下是您要求我运行的查询的一些结果:` -7.0000000000000007E-2 -5.0000000000000003E-2 -5.0000000000000003E-2 5.999999999999998E9999999999999999。 2.9999999999999999E-2 -5.0000000000000003E-2 2.9999999999999999E-2 -4.0000000000000001E-2 4.0000000000000001E-2`
  • 评论不是此类信息的地方。请编辑您的帖子。

标签: sql sql-server casting type-conversion alteryx


【解决方案1】:

这个5.9999999999999998E-2 不能直接转换为十进制(7,2),尽管它可以转换为float,然后可以转换为十进制(7,2)。 EG

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 Price from Clone3 WHERE TRY_CONVERT(decimal(7,2),Price) IS NULL; 的结果转换为浮点数?该查询仅产生 239 个结果,所以我的想法是,在将这些数据类型更改为浮点数后,我可以在整个数据集上运行嵌套 cast 语句的另一部分。想法?
【解决方案2】:

最有效的方法可能是清空表并重新加载:

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;

更新记录的开销更大。

【讨论】:

  • 这并不能解决错误“将数据类型 nvarchar 转换为数字时出错。”
  • 感谢戈登的回复!您知道复制表格需要多长时间(同样是 10M+ 记录并且每小时计数)?另外,'truncate table' 语句的目的是什么?
  • 不需要将行复制两次。如果采用这条路线,插入到具有所需结构的新表中并删除和重命名会更有效
  • @MartinSmith。 . .重新插入会保留索引、触发器和约束。
  • 它们可以很容易地添加到空表中,从而不必复制所有行两次(如果您甚至希望触发器为此迁移插入触发)
猜你喜欢
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 2013-10-08
  • 1970-01-01
  • 2013-10-30
相关资源
最近更新 更多