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

Conversion failed error when using SELECT TOP but no error when selecting all rows

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 Conversion failed when converting date and/or time from character string.

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

结果:(24934 行受影响)

这让我很困惑。为什么 SELECT 在第二个场景中给出错误,而在第三个场景中却没有。

在某些情况下可能会发生这种情况。通常,这种类型的转换错误出现在类型不兼容的 select 表达式或 where 表达式中。

您的结果表明:

  • 数据中有坏行。
  • 这些正在被视图过滤掉。
  • 视图可以更改查询计划,因此有时会评估坏行,有时不会。

我的最佳猜测是您发现查询计划发生了变化。当您 select 95 行时,查询计划正在处理数据并发现错误。错误的行稍后会被过滤掉,但错误已经发生了。

当您 select 所有行时,查询计划发生变化并且错误不再发生,因为过滤发生在转换错误之前。

例如,考虑这个查询:

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 作为驱动 table,对所有行执行“5”上的过滤器。但只有 t2 中的匹配行会被过滤。所以,没有错误发生。

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

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