我试图更好地了解最近在生产中发生的一个问题。
一直在正常运行的查询突然停止,并显示以下错误:
传递给LEFT或SUBSTRING函数的长度参数无效。
查询(稍微简化):
SELECT t.client
FROM acuhistr t
,acuheader h
,acrclient c
WHERE t.ext_inv_ref IN (
SELECT substring(ext_inv_ref, 1, len(ext_inv_ref) - 3)
FROM acutrans
WHERE ext_inv_ref LIKE '%ROT'
AND client = t.client
)
AND t.apar_id = h.apar_id
AND c.client = t.client
AND h.client = c.leg_act_cli
我可以通过向substring()传递一个负长度参数来重现此错误消息:
SELECT substring('test', 1, -1)
传递给子字符串函数的长度参数无效。
acutrans表确实包含ext_inv_ref为空的行,但这些行应该已被LIKE条件筛选掉。如果我单独运行子查询,它将成功运行。
我还尝试在开发环境中运行完整的查询,它工作正常。
比较prod和dev之间的查询计划,似乎是prod查询计划在应用LIKE '%ROT'条件之前执行SUBSTRING(),这导致查询失败。
Image comparing query plans between prod and dev
我将新的查询计划确定为查询停止工作的原因,对吗?如果是,SQL Server为什么生成中断查询的计划?
SQL Server版本为2019
1条答案
按热度按时间vohkndzv1#
因为过滤器和表达式可能会以不同的顺序求值(例如,在过滤掉中断的值之前或之后)。更简单地想一想,假设你是一个理发师,大厅里挤满了顾客:
与
下面是SQL Server中一个更简单的示例:
与
在SQL Server中解决此问题的一种方法是使用
CASE
表达式仅计算不中断表达式的行(或者,在本例中,更改表达式使其不中断):用简单的英语来说,这只是说删除最右边的3个字符,但 * 只有 * 如果字符串已经至少有3个字符长。
或者you can use
COALESCE/NULLIF
或其他各种方法,具体取决于输入小于3个字符时是要空字符串还是NULL。其他一些问题,以获得更多见解: