在过去一天左右的时间里,我一直在为这个问题绞尽脑汁——我只是不明白为什么一个过程在一个环境中工作,但由于转换错误(相同的数据,相同的代码)而在另一个环境中失败。
工作服务器的(大幅缩减版本)计划在这里:https ://www.brentozar.com/pastetheplan/?id=B1jZWTfOf
(这似乎不起作用,所以我已将计划 XML 上传到此处的 pastebin:https ://pastebin.com/47Q6nniw )
导致问题的相关列的一些背景:
propertyInst 表包含一个名为 ValueStr 的列,它是 nvarchar 数据类型。GeneralLedgerCode 表有一个数据类型为 int 的列 id。我们的开发人员正在尝试连接两个表。ValueStr 列包含文本数据、XML 数据、int 数据、十进制数据等。理所当然地,我们决定添加一个函数以确保只解析整数 (ISNUMERIC(ValueStr) = 1)。我们没有意识到的是,这也会尝试转换任何十进制值——这会导致自然生产中的转换错误:
将 nvarchar 值“0.1”转换为数据类型 int 时转换失败。
我的问题是,鉴于 propertyInst 表的表扫描将获取包括小数在内的所有数值,为什么标量运算符中的隐式转换不会因相同的转换错误而失败?ISNUMERIC 查询的输出返回其中一些小数。我根本看不出附加的计划是如何运作的。
隐式转换运算符是否永远不会完全失败,转换错误是否来自散列匹配运算符中的探测残差?再一次,当隐式转换失败时,这个值怎么可能传给运算符呢?
作为一个小小的帮助,这里提供了计划图像,其中圈出了我要询问的计算标量。
此外,我可以看到没有针对标量运算符记录的实际行——这是否意味着由于转换错误,引擎决定在运行时不使用该特定运算符?
任何帮助,将不胜感激。
compute scalar operator的计算被推迟到实际使用的时候(Node ID = 1的probe residual),并且之前的Hash Match(Node ID = 3)过滤掉了你可能失败的行。
查看Paul White 的计算标量、表达式和执行计划性能以获取更多信息。
执行计划中没有迹象表明表达式的评估被推迟,或者它实际评估的时间(在哪个节点)。您通常可以使用
CASE
(附带评估顺序保证)和/或TRY_CONVERT
.相关 Microsoft 反馈:SQL Server 不应引发不合逻辑的错误