【问题标题】:MySQL #1093 - You can't specify target table 'giveaways' for update in FROM clauseMySQL #1093 - 您不能在 FROM 子句中指定目标表“赠品”进行更新
【发布时间】: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)

标签: mysql sql select subquery mysql-error-1093


【解决方案1】:

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

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

【讨论】:

  • 谢谢它的工作!但是你能解释一下,我应该选择哪种方式来表现?你的?还是@nick rulez (stackoverflow.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 的 (stackoverflow.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】:

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

    【讨论】:

      猜你喜欢
      • 2016-05-19
      • 2015-06-08
      • 2015-07-11
      • 1970-01-01
      • 2018-06-04
      • 2013-04-09
      • 1970-01-01
      • 2014-01-29
      • 2018-11-15
      相关资源
      最近更新 更多