2

我从 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 转换为浮点数时出错。

这是在 Sql Server 2008 SP2 上

4

3 回答 3

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 to FLOAT 并不完全一致。我知道 ISNUMERIC 接受逗号和美元符号(可能还有其他字符)。您也可以试试这个(假设您使用美国风格的数字格式):

select (case when isnumeric(amountstr) = 1
             then cast(replace(replace(amountstr, ',', ''), '$', '') as float) end) as Amount
于 2012-08-21T02:01:18.617 回答
0

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

于 2012-08-21T01:44:45.503 回答
0

如果您在前面提到的基础视图中进行转换,则只有错误数据导致查询失败的可能性。你有空值吗?您是否尝试过对金额使用 IsNull() 函数,以便将任何空/坏数据清零?

于 2018-08-19T19:11:55.580 回答