隐式转换有时会导致错误

Geo*_*ios 4 sql-server execution-plan type-conversion errors sql-server-2014

在最后一天左右的时间里,我一直在为这个问题摸不着头脑——我只是不明白为什么一个过程在一种环境中有效,但由于转换错误(相同的数据,相同的代码)而在另一种环境中失败。

工作服务器的计划(大幅削减版本)位于: https: //www.brentozar.com/pastetheplan/ ?id=B1jZWTfOf

(这似乎不起作用,所以我已将计划 XML 上传到此处的 Pastebin: https: //pastebin.com/47Q6nniw

导致问题的相关列的一些背景知识:

propertyInst 表包含一个名为 ValueStr 的列,它是 nvarchar 数据类型。GeneralLedgerCode 表具有数据类型 int 的列 id。我们的开发人员正在尝试连接两个表。ValueStr 列保存文本数据、XML 数据、整数数据、小数数据等。当然,我们决定添加一个函数来确保仅解析整数 (ISNUMERIC(ValueStr) = 1)。我们没有意识到的是,这也会尝试转换任何十进制值 - 这会导致自然生产中的转换错误:

将 nvarchar 值“0.1”转换为数据类型 int 时转换失败。

我的问题是,鉴于 propertyInst 表的表扫描将拾取包括小数在内的所有数值,为什么标量运算符中的隐式转换不会因相同的转换错误而失败?ISNUMERIC 查询的输出返回其中一些小数。我根本看不出所附计划是如何运作的。

隐式转换运算符是否永远不会彻底失败,转换错误是否来自哈希匹配运算符中的探测残差?话又说回来,当隐式转换失败时,该值如何能够到达运算符呢?

作为一个小帮助,计划图像在这里,我要询问的计算标量被圈起来。

计划

此外,我可以看到没有针对标量运算符记录的实际行 - 这是否意味着引擎由于转换错误而决定在运行时不使用该特定运算符?

计划2

任何帮助,将不胜感激。

Mik*_*son 5

计算标量运算符的计算被推迟到实际使用时(节点 ID = 1 的探测残差),并且之前的哈希匹配(节点 ID = 3)会过滤掉对您来说失败的行。

有关更多信息,请参阅Paul White 的《计算标量、表达式和执行计划性能》

执行计划中没有任何迹象表明表达式的求值被推迟,或者何时(在哪个节点)实际求值。通常,您可以使用CASE(带有评估顺序保证)和/或 来防御性地编写代码TRY_CONVERT

相关 Microsoft 反馈:SQL Server 不应引发不合逻辑的错误