将NVARCHAR转换为MONEY或FLOAT格式

时间:2013-08-21 16:29:13

标签: sql-server-2008

我的问题:我有一个表(从Excel导入到SQL Server 2008),它以NVARCHAR(255)格式存储数字。

尝试将这些列转换为FLOATMONEYNUMERICCONVERTCAST函数失败:

ORIGBAL   = CAST(ORIGBAL AS FLOAT)
ORIGBAL   = CAST(ORIGBAL AS MONEY)
ORIGBAL   = CAST(ORIGBAL AS MONEY)
ORIGBAL   = CONVERT(decimal(12,2),ORIGBAL)

消息在所有情况下(或类似的失败错误消息):

  

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

2 个答案:

答案 0 :(得分:2)

听起来,因为你有一个存储在字符串列中的数字数据,你有坏数据。识别它的一种方法是:

SELECT key_column, ORIGBAL
  FROM dbo.tablename
  WHERE ORIGBAL LIKE '%[^-.0-9]%';

修复该数据(它可能包含逗号,但可能损坏比这更糟,就像一些具有完全非数字数据的值 - 否则转换为MONEY应该有效)。如果您发现很多行包含逗号,那么您只需运行更新:

UPDATE dbo.tablename SET ORIGBAL = REPLACE(ORIGBAL, ',', '');

然后再次运行上面的查询。如果没有返回任何行,现在您可以转换为“普通”数字类型而不是MONEYFLOAT,这些类型确实应该保留用于非常具体的场景恕我直言。

在不修复数据的情况下,您可以在所有查询中使用CASE表达式,从而使您的生活更加复杂:

SELECT key_column, CONVERT(DECIMAL(12,2), CASE 
  WHEN ORIGBAL LIKE '%[^-.0-9]%' THEN ORIGBAL END
FROM dbo.tablename
...

这将产生NULL值,而不是错误的非数字值。然而它仍然可能失败,例如该表达式将传递0.0.0.44.02,显然无法转换为小数。举个例子:

DECLARE @x TABLE(ORIGBAL NVARCHAR(255));

INSERT @x VALUES('bob'),('0.0.0.44.02'),('32500.40');

SELECT ORIGBAL, [status] = CASE WHEN ORIGBAL LIKE '%[^.0-9]%' 
  THEN 'needs correcting' ELSE 'all good' END
FROM @x;

结果:

bob          needs correcting
0.0.0.44.02  all good
32500.40     all good

要识别具有多个小数点的案例,您可以这样做:

SELECT ORIGBAL, [status] = CASE WHEN ORIGBAL LIKE '%[^.0-9]%'
  OR LEN(ORIGBAL)-LEN(REPLACE(ORIGBAL,'.','')) > 1 
  THEN 'needs correcting' ELSE 'all good' END
FROM @x;

结果:

bob          needs correcting
0.0.0.44.02  needs correcting
32500.40     all good

您仍然可能拥有超过最终转换的值,例如'12345678901234.56' DECIMAL(12,2)太大了。

在SQL Server 2012中,您将获得上述表达式的简写:

SELECT key_column, TRY_CONVERT(DECIMAL(12,2), ORIGBAL)
FROM dbo.tablename
...

...即使对于NULL等更复杂的值, 会产生0.0.0.44.02个值。

答案 1 :(得分:0)

CAST对逗号和美元符号反应不佳。你可能会有更好的运气CONVERT ...

SELECT CONVERT(money, '$1,123.45')

如果必须以十进制表示,请转换为金钱,然后是十进制......

SELECT CAST(CONVERT(money, '$1,123.45') AS decimal(12,2))