2017-05-31 125 views
0

我有一个列可以存储文本,但用于存储一个数字(我没有制造系统!)有人已经把一个空值(即不是内容,但不空)及其导致的错误: -转换数据类型(varchar)仍然显示转换错误

Msg 8114, Level 16, State 5, Line 1

Error converting data type varchar to numeric.

我有问题降低到以下: -

SELECT 
    T1.[FIELD_5], 
    ISNUMERIC(T1.[FIELD_5]), 
    NULLIF(T1.[FIELD_5],''), 
    ISNULL(NULLIF(T1.[FIELD_5],''),0), 
    CONVERT(DECIMAL(18,5),ISNULL(NULLIF(T1.[FIELD_5],''),0)) 
FROM 
    [MyTBL] T1 
ORDER BY 
    ISNUMERIC(T1.[FIELD_5]) 

问题的数据是[FIELD_5]

  1. 我可以看到SQL认为的不是数字的值
  2. 我可以看到NULLIF成功将其更改为一个NULL
  3. 我可以看到ISNULL正在转动NULLIF结果0

但在CONVERT上的错误消息ISNULL结果的结果,我希望它导致0.00000

+0

SQL服务器的什么版本?在以后的版本中,您可以使用TRY_PARSE – DhruvJoshi

+0

您确定没有空格或不可打印的字符吗?你知道'ISNUMERIC()'的局限性吗? – HoneyBadger

+0

我无法解释它是如何被捕获的,但我已经给出了解释'1E-07'的解释,并将其视为数字。 –

回答

0

这是一个需要更好的调查的情况下,我应该已经意识到,因为我认为SQL不通常是用户错误。

我再次运行它而没有order by子句,然后选择在显示最后一行(即导致错误的那行)后显示的行。

[FIELD_5]包含值为1E-07,这是一个臭名昭着的Excel导入错误!

什么不加起来就是为什么当我通过ISNUMERIC开始订单时,我没有在列表顶部看到这个值,只有确实正确管理的空白值。

问题解决了,我应该坚持调查,但我认为这值得留下来帮助未来的其他调查。

+1

如果你运行'SELECT ISNUMERIC('1E-07')',你会看到它返回'1'。在评估数字时,“ISNUMERIC()”是非常宽容的。像'$,+,-'这样的字符都被评估为1。 – HoneyBadger

+1

>>>什么不加起来就是为什么当我通过ISNUMERIC订购时,我没有在列表顶部看到这个值,只有确实正确管理的空白值。<<< isnumeric( 1E-07)= 1,这就是为什么当你用isnumeric命令时它不会弹出。 Isnumeric看起来并不是你想要转换成十进制(18,5),它只是告诉你它是否可以转换为某种数字类型,并且是的,1E-07会。它可以转换为浮动 – sepupic

2

使用try_convert()

SELECT T1.[FIELD_5], ISNUMERIC(T1.[FIELD_5]), NULLIF(T1.[FIELD_5], ''), 
     COALESCE(NULLIF(T1.[FIELD_5], ''), 0), 
     TRY_CONVERT(DECIMAL(18, 5), COALESCE(NULLIF(T1.[FIELD_5], ''), 0)) 
FROM [MyTBL] T1 
ORDER BY ISNUMERIC(T1.[FIELD_5]); 

try_convert()在SQL Server 2012中引入。如果您使用的是早期版本,那么您需要使用case表达式。

(我切换ISNULL()COALESCE()因为我喜欢那里的实际使用ANSI标准的功能。)

0

有一些可用非数字值,你可以这样做检查以案例如下:

select convert(decimal(18,5), '') 

抛出误差为“错误数据类型为varchar转换为数字。 ”

SELECT 
    T1.[FIELD_5], 
    ISNUMERIC(T1.[FIELD_5]), 
    NULLIF(T1.[FIELD_5],''), 
    ISNULL(NULLIF(T1.[FIELD_5],''),0), 
    CONVERT(DECIMAL(18,5), iif(isnumeric(ISNULL(T1.[FIELD_5]),'0') > 1,T1.[FIELD_5],'0') 
    ISNULL(NULLIF(T1.[FIELD_5],''),0)) 
FROM 
    [MyTBL] T1 
ORDER BY 
    ISNUMERIC(T1.[FIELD_5]) 
1

SQL2012 +

为了找到那些无效DECIMAL|NUMERIC(18, 5)我会使用从而TRY_PARSETRY_CONVERT函数的值:

SELECT 
    T1.ID, 
    NULLIF(T1.[FIELD_5], '') AS FIELD_5_WithNULLIF 
FROM 
    [MyTBL] T1 
WHERE 
    T1.[FIELD_5] IS NOT NULL -- It removes from end results NULLs (FIELD_5) 
    AND T1.[FIELD_5] <> '' -- It removes empty or SPACE(n) values (FIELD_5) 
    AND TRY_PARSE(T1.[FIELD_5] AS DECIMAL(18, 5)) IS NULL -- It removes invalid DECIMAL(18, 5) values (FIELD_5) 

TRY_PARSE行为是如下:如果源字符串值[N][VAR]CHAR是一个有效的DECIMAL|NUMERIC(18, 5)然后它返回该值与新的数据类型否则它返回NULL - >所以它不会引发异常(“错误”)。

参见:Use new TRY_PARSE() instead of ISNUMERIC() | SQL Server 2012

现在,如果你要转换的空字符串,也无效源的值设为NULL,然后我会用

SELECT 
    T1.ID, 
    T1.[FIELD_5] AS OriginalValue, 
    TRY_PARSE(T1.[FIELD_5] AS DECIMAL(18, 5)) AS ConvertedValue 
FROM 
    [MyTBL] T1 
相关问题