2012-02-03 162 views
3

其中运行该SQL查询目前排除问题:SQL Server 2008中:错误转换数据类型为nvarchar浮动

UPDATE tblBenchmarkData 
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID, 
    DataValue = CAST(DataValue AS float) * 1.335 
WHERE 
    FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
    AND ZEGCodeID IN 
      (SELECT ZEGCodeID FROM tblZEGCode 
       WHERE(ZEGCode = 'C004') OR 
        (LEFT(ZEGParentCode, 4) = 'C004')) 

导致以下错误:

Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.

真正奇怪的是,如果我将UPDATE更改为SELECT以检查检索的值是数值:

SELECT DataValue 
FROM tblBenchmarkData 
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
AND ZEGCodeID IN 
     (SELECT ZEGCodeID 
      FROM tblZEGCode WHERE(ZEGCode = 'C004') OR 
           (LEFT(ZEGParentCode, 4) = 'C004')) 

下面是结果:

DataValue 
2285260 
1205310 

想用TRY_PARSE或类似的东西;但是,我们正在运行SQL Server 2008而不是SQL Server 2012.有没有人有任何建议? TIA。

回答

5

这将是有益的,看看tblBenchmarkData的架构定义,但你可以尝试在你的查询中使用ISNUMERIC。喜欢的东西:

SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335 
        ELSE 0 END 
+0

'当isnumeric(datavalue)= 1'时,否则不会编译。 – GSerg 2012-02-03 23:20:38

+0

@GSerg,谢谢! – csm8118 2012-02-03 23:27:26

+0

谢谢,效果很好! – Roger 2012-02-06 17:57:58

2

执行顺序并不总是符合人们的期望。

如果设置了where子句,通常并不意味着select列表中的计算仅适用于与where匹配的行。 SQL Server可能很容易决定进行批量计算,然后筛选出不需要的行。

这就是说,你可以随便写try_parse自己:

create function dbo.try_parse(@v nvarchar(30)) 
returns float 
with schemabinding, returns null on null input 
as 
begin 
    if isnumeric(@v) = 1 
    return cast(@v as float); 

    return null; 
end; 
+0

优秀的提示!谢谢。 – Roger 2012-02-06 17:58:48

1

所以与同时给人一种错误的更新查询开始(请原谅我改写为我自己的清晰度):

UPDATE B 
SET 
    OriginalValue = DataValue, 
    OriginalUnitID = DataUnitID, 
    DataValue = CAST(DataValue AS float) * 1.335 
FROM 
    dbo.tblBenchmarkData B 
    INNER JOIN dbo.tblZEGCode Z 
     ON B.ZEGCodeID = Z.ZEGCodeID 
WHERE 
    B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
    AND (
     Z.ZEGCode = 'C004' OR 
     Z.ZEGParentCode LIKE 'C004%' 
    ) 

我想你会发现,一个SELECT语句完全相同的表达式可以得到同样的错误:

SELECT 
    OriginalValue, 
    DataValue NewOriginalValue, 
    OriginalUnitID, 
    DataUnitID OriginalUnitID, 
    DataValue, 
    CAST(DataValue AS float) * 1.335 NewDataValue 
FROM 
    dbo.tblBenchmarkData B 
    INNER JOIN dbo.tblZEGCode Z 
     ON B.ZEGCodeID = Z.ZEGCodeID 
WHERE 
    B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
    AND (
     Z.ZEGCode = 'C004' OR 
     Z.ZEGParentCode LIKE 'C004%' 
    ) 

这应该告诉你,不能转换行:

SELECT 
    B.* 
FROM 
    dbo.tblBenchmarkData B 
    INNER JOIN dbo.tblZEGCode Z 
     ON B.ZEGCodeID = Z.ZEGCodeID 
WHERE 
    B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5' 
    AND (
     Z.ZEGCode = 'C004' OR 
     Z.ZEGParentCode LIKE 'C004%' 
    ) 
    AND IsNumeric(DataValue) = 0 
    -- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work 

最后一条注释行中的诀窍是将事物绑定到字符串以强制只有有效的数字为数字。例如,如果您只需要整数,IsNumeric(DataValue + '.0E0') = 0会显示那些不是。

+0

感谢您的反馈!我也遇到过的一个问题是,如果数据是以科学计数法表示的,CAST不起作用。所以要解决这个问题,执行一个数据库视图,将科学数据库中的所有数字都变为科学记数法,例如,DataValue 2.86777e + 006 5.43724e + 006 – Roger 2012-02-06 18:02:23

+0

Aha,如果你真的有科学记数法,那么我的技巧就是'E0 '将无法工作。但是IsNumeric函数应该仍然能够帮助你。 – ErikE 2012-02-06 18:03:28

相关问题