UPDATE 查询更改了没有 WHERE 子句但有 AND 子句的行 - 为啥?

Posted

技术标签:

【中文标题】UPDATE 查询更改了没有 WHERE 子句但有 AND 子句的行 - 为啥?【英文标题】:UPDATE query changed rows without a WHERE clause but had an AND clause - why?UPDATE 查询更改了没有 WHERE 子句但有 AND 子句的行 - 为什么? 【发布时间】:2011-08-31 16:12:32 【问题描述】:

我运行了以下查询,它应该有一个 where 子句,但我忘了添加它:

UPDATE
tblFormElementInstances as fei
JOIN
tblFormElements as fe using(intFormElementId)
SET
fei.intStep = 1
AND
fei.intDivisionId = 1 OR fei.intDivisionId IS NULL);

mysql 返回以下消息:

--查询正常,影响 42 行(0.06 秒) --匹配行:94 更改:42 警告:0

我原以为它会引发语法错误,但事实并非如此。此外,该表中有 96 行,具有不同的 intDivisionIds(即不仅仅是 1 或 NULL),这表明 MySQL 完成了一些过滤(匹配的行数 = 94)。

另外,intStep 实际上改为 0,而不是 1。

有谁知道:

1) 为什么这个查询有效? 2) 为什么将 intStep 更改为 0 而不是 1? 3) 为什么不匹配所有 96?

(更改为 42 的计数是因为某些行已经有 intStep = 1。)

【问题讨论】:

这里必须有语法错误,因为右括号不匹配。 是的,抱歉,AND 后面有一个括号,我在粘贴查询时必须删除它。 【参考方案1】:

它没有语法错误,因为1 AND <expr> 是一个有效的表达式。

您将 intStep 设置为该表达式(我已添加括号以显示优先级):

SET intStep = ((1 AND (fei.intDivisionId = 1)) OR (fei.intDivisionId IS NULL))

这是一个布尔表达式,为 0 或 1,因此它将某些行更改为 0,将某些行更改为 1。如果 intDivisionId 不为 1,并且如果 intDivisionId 不为 null,则更改为 0。

我猜你在 tblFormElementInstances 中有 96 行,但这些行中只有 94 行在 tblFormElements 中有匹配的行。 JOIN 意味着只有匹配的行才有资格进行 UPDATE。

试试这个查询来测试这个理论,我敢打赌它会返回 94:

SELECT COUNT(*) FROM tblFormElementInstances as fei
JOIN tblFormElements as fe using(intFormElementId)

@Jason McCreary 很好地观察到您的示例末尾有一个不平衡的括号。这应该会导致语法错误。由于您说您没有收到语法错误,因此我认为括号是错误地包含在您的示例中。

【讨论】:

太棒了,谢谢你完美的回答!你是对的,选择查询返回 94。【参考方案2】:
    不确定。我同意尾随的单独) 应该导致语法错误。也许 MySQL 没有那么严格。 因为1 AND fei.intDivisionId = 1 OR fei.intDivisionId IS NULL 的结果是0。正如您自己指出的那样,第一个 AND 应该是 WHERE 您的 JOIN 很可能与 other 表中的 2 行不匹配。

【讨论】:

1 - 我在 AND 之后错过了一个开头的括号,怀疑 MySQL 是否松懈 :)

以上是关于UPDATE 查询更改了没有 WHERE 子句但有 AND 子句的行 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

UPDATE 查询的 WHERE 子句中的 SELECT 查询 [重复]

使用更改的 WHERE 子句访问直通查询

sql中的update操作时 如果没有用到where子句会怎么样?

WHERE 子句中带有子查询的 MYSQL UPDATE 查询 - 优化

如何在 SQL UPDATE 语句 WHERE 子句中读取脏值

在update语句中使用where子句的目的是啥?