使用SELECT TOP时转换失败错误,但选择所有行时没有错误

时间:2018-05-29 15:44:24

标签: sql sql-server tsql type-conversion sql-server-2017

SSMS - SQL 2017 我正在从视图中选择记录 - 3个场景,并且查询失败,其中一个有错误。

SELECT top 94 *
FROM [myDB].[dbo].[test1]

结果:(94行受影响)

SELECT top 95 *
FROM [myDB].[dbo].[test1]

结果:

  

Msg 241,Level 16,State 1,Line 2   从字符串转换日期和/或时间时转换失败。

SELECT *
FROM [myDB].[dbo].[test1]

结果:(受影响的24934行)

这让我很困惑。 SELECT如何在第二个场景中给出错误而在第三个场景中没有错误。

1 个答案:

答案 0 :(得分:2)

有些情况会发生这种情况。通常,此类转换错误位于select表达式或where表达式中,其类型不兼容。

你的结果是:

  • 数据中存在错误的行。
  • 这些视图已被过滤掉。
  • 视图可以更改查询计划,因此有时会对坏行进行评估,有时则不会。

我最好的猜测是你看到了查询计划的变化。当您选择95行时,查询计划正在处理数据并查找错误。有错误的行将在稍后过滤掉,但错误已经发生。

当您选择所有行时,查询计划会更改,并且不再出现错误,因为过滤发生在转换错误之前。

例如,请考虑以下问题:

select . . .
from t1 join
     t2
     on t1.x = t2.x
where t1.col1 = 5 and
      cast(t2.col2 as date) = cast(getdate() as date);  -- this generates the error

这可以通过两种方式进行评估。使用t1作为驱动表,对所有行执行“5”的过滤器。但是只会过滤t2中匹配的行。所以,不会发生错误。

或者,可以过滤t2并将过滤器应用于所有行。错误!我们永远不会进一步了解错误行会被过滤掉。

执行计划的选择可以基于返回的行数。或者,成本可能完全相同,SQL Server任意选择其中一个。