MySQL #1093 - 您不能在 FROM 子句中指定目标表“赠品”进行更新

Posted

技术标签:

【中文标题】MySQL #1093 - 您不能在 FROM 子句中指定目标表“赠品”进行更新【英文标题】:MySQL #1093 - You can't specify target table 'giveaways' for update in FROM clause 【发布时间】:2012-01-10 03:03:45 【问题描述】:

我试过了:

UPDATE giveaways SET winner = '1' WHERE ID = (SELECT MAX(ID) FROM giveaways)

但它给出了:

#1093 - 您不能在 FROM 子句中指定要更新的目标表“赠品”

This article 似乎相关,但我无法使其适应我的查询。我怎样才能让它工作?

【问题讨论】:

您正在执行递归查询。你到底想做什么? giveaways表的记录很少。我想将赠品(具有最大 ID)的获胜者列设置为 1 @Gigi,很明显他想做什么。 UPDATE giveaways SET winner = '1' WHERE ID = (SELECT MAX(ID) FROM giveaways) 【参考方案1】:

根据您链接到的文章中的信息应该可以:

update giveaways set winner='1'
where Id = (select Id from (select max(Id) as id from giveaways) as t)

【讨论】:

谢谢它的工作!但是你能解释一下,我应该选择哪种方式来表现?你的?还是@nick rulez (***.com/a/8333417/556169)? @Eray 这个答案和上面的 nick rulez' 答案是等价的,但是它们都使用了这里不需要的嵌套子查询。 @Eray。我认为我的查询不会比 ipr101 慢,因为即使我使用 *,查询也只检索一个标量值。所以我没有得到任何不必要的价值。顺便说一句,我赞成马修的回答,因为它是更聪明的解决方案,我不明白为什么有人反对它。 @Pacerier 将其保存到变量中然后使用该变量将不再是巧合编码,而是会引入竞争条件。 @Pacerier 你不会,你会得到一个竞争条件。如果您不想要竞争条件,则需要一个表锁。这本质上不是死锁。【参考方案2】:

这是因为您的更新可能是周期性的......如果更新该记录导致发生WHERE 条件FALSE 的事情怎么办?你知道情况并非如此,但引擎不会。操作中也可能存在桌子上的对立锁。

我认为你可以这样做(未经测试):

UPDATE
    giveaways
SET
    winner = '1'
ORDER BY
    id DESC
LIMIT 1

Read more

【讨论】:

已经过测试和批准。耗时 0.0002 秒。 @Matthew,关于 “如果更新该记录会导致发生WHERE 条件FALSE 的事情怎么办?”,因为where 子句已经评估,为什么这很重要?为什么 mysql 不够聪明,无法自动执行此操作(ipr101 和 nick 的回答)? @Pacerier 原因是这些解决方案对嵌套子查询使用隐式查询。当您告诉引擎从嵌套子查询中选择内容时,您隐含地强制它首先执行该语句。如果不这样做(如所写),查询计划器将尝试优化嵌套。这是巧合的编码,这意味着您依赖于查询计划器的特定行为并且是不好的做法。 @Matthew,那么,真正的问题不是与“查询规划器将尝试优化嵌套”有关吗?在像update t where id=(select max(id)from t) 这样的查询中,很明显查询规划器不应该尝试优化嵌套,因为可以看出(select max(id)from t) 是应该首先运行的内部查询。 @Pacerier 否。查询计划器的默认行为通常首先执行嵌套子查询,因为它们可能能够更有效地组合到 out 查询中。这两个答案利用了这个明确的SELECT,迫使查询计划者的行为。这当然有效,但对计划者不利。这是巧合的编码。您无法控制查询计划器的行为方式,并且您不应编写代码以利用其巧合行为。【参考方案3】:
update giveaways set winner=1 
where Id = (select*from (select max(Id)from giveaways)as t)

【讨论】:

谢谢它的工作!但是你能解释一下,我应该选择哪种方式来表现?你的?还是 @ipr101 的 (***.com/a/8333445/556169)? 我的查询和ipr101的查询是一样的。他们只是使用临时表解决方法来避免您报告的错误。顺便说一句,马修的解决方案也很好。 ;)【参考方案4】:
create table GIVEAWAYS_NEW as(select*from giveaways);

update giveaways set winner=1
where Id=(select max(Id)from GIVEAWAYS_NEW);

【讨论】:

复制整个表格,性能会不会很糟糕? 它还有并发问题:由于您使用多个语句,您可能需要将其包装在事务中,否则赠品中的最大 Id 可能会在 create tableupdate 之间变化.【参考方案5】:

利用TEMP TABLE:

如下:

UPDATE TABLE_NAME SET TABLE_NAME.IsActive=TRUE
WHERE TABLE_NAME.Id IN (
    SELECT Id
    FROM TEMPDATA
);

CREATE TEMPORARY TABLE TEMPDATA
SELECT MAX(TABLE_NAME.Id) as Id
FROM TABLE_NAME
GROUP BY TABLE_NAME.IncidentId;

SELECT * FROM TEMPDATA;

DROP TABLE TEMPDATA;

【讨论】:

【参考方案6】:

您可以先创建子查询的视图,然后从视图中更新/删除选择。 请记住在之后删除视图。

【讨论】:

以上是关于MySQL #1093 - 您不能在 FROM 子句中指定目标表“赠品”进行更新的主要内容,如果未能解决你的问题,请参考以下文章

MySQL绕过错误1093

#1093 - 您不能在 FROM 子句中指定目标表 'comments' 进行更新

#1093 - 您不能在 FROM 子句中指定目标表 'tbl' 进行更新 [重复]

#1093 - 您不能在 FROM 子句中指定要更新的目标表 [重复]

无法运行查询给出 mySQL 错误 #1093 - 您无法在 FROM 子句中指定目标表“成员”进行更新 [重复]

mysql 1093错误