我尝试了:
UPDATE giveaways SET winner = '1' WHERE ID = (SELECT MAX(ID) FROM giveaways)
但是它会给出以下错误信息:
#1093 - 无法在
FROM
子句中指定目标表 'giveaways' 进行更新
这篇文章看起来很相关,但我无法将其适应到我的查询中。我该如何让它工作?
基于您提供的文章信息,以下内容应该有效:
update giveaways set winner='1'
where Id = (select Id from (select max(Id) as id from giveaways) as t)
start transaction
和commit
来包围这些语句。这样就不会出现竞争条件了。 - PacerierWHERE
条件变为FALSE
,会发生什么? 你知道这不是真的,但引擎不知道。操作表中也可能存在相反的锁定。UPDATE
giveaways
SET
winner = '1'
ORDER BY
id DESC
LIMIT 1
WHERE
条件为FALSE
的情况发生”的问题,既然where
子句已经被评估过了,那为什么这会有影响呢?为什么MySQL不能自动地做到这一点(ipr101和nick的回答)? - Pacerierupdate t where id=(select max(id)from t)
这样的查询中,很明显查询规划器不应该尝试优化嵌套,因为可以看出(select max(id)from t)
是应该首先运行的内部查询。 - PacerierSELECT
,强制查询规划器的行为。当然,这样做是可以的,但是这是在反对规划器。这是巧合编码。您无法控制查询规划器的行为,也不应该编写代码以利用其巧合的行为。 - Matthewupdate t where id=(select max(id)from t)
有一个循环,因此对于这些情况,它很容易告诉自己首先执行嵌套子查询。对于未检测到循环的情况,只要结果是引用透明的,它就可以自由地以任何方式组合查询。 - Pacerierupdate giveaways set winner=1
where Id = (select*from (select max(Id)from giveaways)as t)
您可以先创建子查询的视图,然后通过从该视图中选择进行更新/删除操作。 只需记得在操作完成后删除该视图即可。
create table GIVEAWAYS_NEW as(select*from giveaways);
update giveaways set winner=1
where Id=(select max(Id)from GIVEAWAYS_NEW);
使用临时表:
如下所示:
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;
UPDATE giveaways SET winner = '1' WHERE ID = (SELECT MAX(ID) FROM giveaways)
* - Pacerier