我从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上
答案 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()函数,以便将所有空/不良数据清零?