MYSQL 更新与 WHERE SELECT 子查询错误

Posted

技术标签:

【中文标题】MYSQL 更新与 WHERE SELECT 子查询错误【英文标题】:MYSQL update with WHERE SELECT subquery error 【发布时间】:2011-10-20 03:00:49 【问题描述】:

我在获取选择子查询以处理 UPDATE 时遇到问题。我正在尝试以下方法:

UPDATE foo
   SET bar=bar-1
 WHERE baz=
      (
       SELECT baz
       FROM foo
       WHERE fooID='1'
      )

其中foo 是主键fooID 的表名。 barbaz 是 INT 类型。执行此操作时出现以下错误:

Error: A query failed. You can't specify target table 'foo' for update 
in FROM clause

【问题讨论】:

SQL Delete: can't specify target table for update in FROM clause的可能重复 ***.com/search?q=specify+target+table 【参考方案1】:

由于错误 1093 错误 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000。 解决方法是创建一个临时表。

CREATE TEMPORARY table foo_bak (SELECT baz from foo WHERE fooID='1');

UPDATE foo
  SET foo.bar=foo.bar-1
WHERE foo.baz =
  (
    SELECT baz
    FROM foo_bak
  );

DROP TABLE foo_bak;

【讨论】:

是的,我尝试命名所有内容,但没有运气......似乎你不能在子查询中使用同一个表......我觉得有点傻。 是的,如果我没记错的话,PostgreSQL 允许这样做。 Dwb 的解决方案要干净得多。 如果你创建了一个临时表,你不需要删除它,因为脚本结束时临时表会自动删除【参考方案2】:

据我所知,在更新表时,mysql 会锁定它以进行安全更新。您无法在尝试时选择数据并更新同一个表。

这些文字应该对你有帮助

http://www.xaprb.com/blog/2006/06/23/how-to-select-from-an-update-target-in-mysql/

http://verysimple.com/2011/03/30/mysql-cant-specify-target-table-for-update-in-from-clause/

【讨论】:

但是子查询不应该是不相关的吗? (即首先运行内部查询,然后运行外部查询)...这是一个非常有用的查询,可以运行,但不允许它看起来很奇怪。 :(【参考方案3】:

来自web article

这个错误的原因是当你在内部选择中使用同一个表作为更新条件时,MySQL 不允许更新表。 文章接着提供了一个解决方案,那就是使用临时表。

使用这个例子,你的更新应该是这样的:

update foo
set bar = bar - 1
where baz in
(
  select baz from
  (
    select baz
    from foo
    where fooID = '1'
  ) as arbitraryTableName
)

【讨论】:

我一有机会就会重新审视这个问题,但只是一个未经检验的想法,我想我会扔在那里:解决 OP 错误的更干净的方法不是在 UPDATE 查询中不使用 any 子选择,而是 JOIN foo 本身?此处的嵌套 SELECT 语句有效,它们是我自从看到您的答案以来一直用于这种情况的解决方案,但它们非常棘手 - 如果 JOIN 有效,感觉就像是“正确”的解决方案。 我同意嵌套选择可能不是最好的解决方案。除了 OP 提出的解决方案之外,我没有考虑其他解决方案。 Join 看起来不错,但是对于 SQL,我通常不愿意说一个有效的解决方案是“正确的”而另一个是“不正确的”。只是不同,也许不太理想。 我尝试了另一种方法,它也有效,更新 foo f, (select baz from foo where fooID = '1') a set f.bar = f.bar - 1 where f.baz = a .baz我的mysql版本是5.6.27-0ubuntu0.14.04.1-log @DWB 至少 MariaDB 10.3 解除了这个限制more【参考方案4】:

在某些情况下,您还可以利用 MySQL 变量。例如:

SET @id1 = (SELECT id FROM foo WHERE name = 'parent');
UPDATE foo SET parent_id = @id1 WHERE name = 'emails';

【讨论】:

以上是关于MYSQL 更新与 WHERE SELECT 子查询错误的主要内容,如果未能解决你的问题,请参考以下文章

第四章 MySQL高级查询

05 MySQL之查询插入更新与删除

sql语句中where条件的嵌套子查询性能

mysql基础语法

MySQL 多表where查询与单表select where in哪一个效率高

20165232 第七周学习总结