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
的表名。 bar
和 baz
是 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 子查询错误的主要内容,如果未能解决你的问题,请参考以下文章