不可能:UPDATE 语句失败而 SELECT 成功

时间:2021-06-03 08:37:22

标签: sql-server tsql sql-update ssms

这个查询怎么可能成功运行:

SELECT ClientIp, LEFT(clientip, CHARINDEX(',', clientip) - 1)
FROM tblIISLog
WHERE clientip LIKE '%,%';

但是此更新语句会引发以下错误:

UPDATE tblIISLog
  SET ClientIp = LEFT(clientip, CHARINDEX(',', clientip) - 1)
WHERE clientip LIKE '%,%';
Msg 537, Level 16, State 2, Line 6
Invalid length parameter passed to the LEFT or SUBSTRING function.
The statement has been terminated.

这是完全相同的表和 where 子句,中间没有添加任何行。这不应该发生,除非 SQL 服务器以某种方式为比预期更多的行计算 LEFT。 有人能解释一下吗?

编辑: 下面已经提供了一种解决方法,但要回答为什么。这是 UPDATE 的查询计划:

enter image description here

这对于 SELECT :

enter image description here

计算标量步骤实际上是在过滤步骤之前执行的,这就是为什么表达式可以跨越 ClientIp 行而没有任何“,”。

2 个答案:

答案 0 :(得分:2)

这并没有回答为什么一个有效而另一个无效的问题,尽管评论涉及它,这是由于在查询计划中可能是 {{1} } 是在 SET 之前派生的(这可能发生)。也许我们上面有一个过于简单的查询,这就是为什么我们看不到明显的原因。

然而,对于避免它,一种方法是使用WHERE

NULLIF

这意味着如果字符串中没有 UPDATE tblIISLog SET ClientIp = LEFT(clientip, NULLIF(CHARINDEX(',', clientip),0) - 1) WHERE clientip LIKE '%,%'; ,表达式将解析为 NULL

答案 1 :(得分:1)

试试这个,以避免将负值传递给左函数:

UPDATE tblIISLog
  SET ClientIp = LEFT(clientip, nullif(CHARINDEX(',', clientip), 0) - 1)
WHERE clientip LIKE '%,%';
相关问题