首页 > 解决方案 > 使用 SELECT TOP 时出现转换失败错误,但选择所有行时没有错误

问题描述

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

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

结果:(受影响的 94 行)

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

结果:

消息 241,级别 16,状态 1,第 2 行从字符串转换日期和/或时间时转换失败。

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

结果:(24934 行受影响)

这让我很困惑。为什么 SELECT 在第二种情况下会出错,而在第三种情况下却没有。

标签: sqlsql-servertsqltype-conversionsql-server-2017

解决方案


在某些情况下可能会发生这种情况。通常,这种类型的转换错误出现在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 随意选择其中之一。


推荐阅读