目前正在解决运行此SQL查询的问题:
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
将数据类型nvarchar转换为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。
答案 0 :(得分:5)
查看tblBenchmarkData的架构定义会很有帮助,但您可以尝试在查询中使用ISNUMERIC。类似的东西:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
答案 1 :(得分: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;
答案 2 :(得分: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
会显示那些不是整数。