SQL Server查询编译 - 将VarChar转换为Float

时间:2012-08-21 01:37:02

标签: sql sql-server

我从SQL Server得到一些奇怪的行为。我有一个返回金额字段的基础视图。该金额字段从VARCHAR(50)转换为FLOAT。

我可以成功运行以下查询:

SELECT AMOUNT
FROM vReturnDetails

我还可以成功运行以下查询:

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear = 2012

同样,我可以运行此查询:

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear <> 2012

这是奇怪的地方,我不能运行以下任何一项:

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear = 2012 OR t.ReturnYear <> 2012

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 

我可以成功运行此查询:

SELECT AMOUNT
FROM vReturnDetails v 
    INNER JOIN MyTable t 
        ON t.LicenceNumber = v.LicenceNumber
        AND t.ReturnYear = v.ReturnYear 
WHERE t.ReturnYear <> 2013 --2013 is a dummy value that doesn't exist

任何人都可以对这里发生的事情有所了解。这对我来说毫无意义,所以我不知道从哪里开始寻找解决问题的方法。

我收到的错误是

将数据类型varchar转换为float时出错。

这是在Sql Server 2008 SP2上

3 个答案:

答案 0 :(得分:2)

SQL Server很复杂。 SQL引擎中的处理顺序不一定与查询中的顺序相同。例如,WHERE子句中的过滤器可以在读取数据时应用,也可以在数据处理后应用。

显然,AMOUNT字段中的某些值不是有效的浮点数。最简单的解释是,当你跑:

SELECT AMOUNT
FROM vReturnDetails

您没有返回所有行。 。 。并且后面有坏数据的行。

或者,vReturnDetails是基于底层数据的视图,其中一些是坏的。编译查询时,可能会影响过滤发生的位置。在某些情况下,引擎可能决定读取所有数据,进行转换,然后继续 - 但是在转换过程中会出现错误,从而导致进程中断。

您可以通过将视图更改为:

来解决此问题
select (case when isnumeric(amountstr) = 1 then cast(amountstr as float) end) as Amount

SQL Server 确保保证case语句中的评估顺序。所以,这不应该返回错误。

ISNUMERIC()和CONVERT到FLOAT并不完全一致。我知道ISNUMERIC接受逗号和美元符号(也许还有其他字符)。您也可以尝试这一点(假设您使用美式格式的数字):

select (case when isnumeric(amountstr) = 1
             then cast(replace(replace(amountstr, ',', ''), '$', '') as float) end) as Amount

答案 1 :(得分:0)

在查询中调用CONVERT的位置令人困惑。从上面的评论中,我了解到AMOUNT是VARCHAR(50)。你把它转换成FLOAT在哪里?

答案 2 :(得分:0)

如果您如上所述在基础视图中执行转换,则仅存在错误数据导致查询失败的可能性。您是否有空值? 您是否尝试过在数量上使用IsNull()函数,以便将所有空/不良数据清零?