您不能在FROM子句中为更新指定目标表

我有一个简单的MySQL表:

CREATE TABLE IF NOT EXISTS `pers` ( `persID` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(35) NOT NULL, `gehalt` int(11) NOT NULL, `chefID` int(11) DEFAULT NULL, PRIMARY KEY (`persID`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; INSERT INTO `pers` (`persID`, `name`, `gehalt`, `chefID`) VALUES (1, 'blb', 1000, 3), (2, 'as', 1000, 3), (3, 'chef', 1040, NULL); 

我试图运行下面的更新,但我只得到错误1093:

 UPDATE pers P SET P.gehalt = P.gehalt * 1.05 WHERE (P.chefID IS NOT NULL OR gehalt < (SELECT ( SELECT MAX(gehalt * 1.05) FROM pers MA WHERE MA.chefID = MA.chefID) AS _pers )) 

我search了错误,发现从http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html页面的MySQL,但它不帮助我。

我该怎么做来纠正SQL查询?

问题是,无论出于什么原因,MySQL都不允许你写这样的查询:

 UPDATE myTable SET myTable.A = ( SELECT B FROM myTable INNER JOIN ... ) 

也就是说,如果你在一个表上执行一个UPDATE / INSERT / DELETE ,你不能在一个内部查询中引用这个表(然而你可以从这个外部表引用一个字段…)


解决方法是用(SELECT * FROM myTable)replace子查询中myTable的实例,就像这样

 UPDATE myTable SET myTable.A = ( SELECT B FROM (SELECT * FROM myTable) AS something INNER JOIN ... ) 

这显然会导致必要的字段被隐式复制到一个临时表中,所以这是允许的。

我在这里find这个解决scheme 这篇文章的一个注释:

你不想在实际的子查询中只SELECT * FROM table ; 我只是想保持简单的例子。 实际上,只应该在最内层的查询中select需要的列,并添加一个好的WHERE子句来限制结果。

你可以通过三个步骤做到这一点:

 CREATE TABLE test2 AS SELECT PersId FROM pers p WHERE ( chefID IS NOT NULL OR gehalt < ( SELECT MAX ( gehalt * 1.05 ) FROM pers MA WHERE MA.chefID = p.chefID ) ) 

 UPDATE pers P SET P.gehalt = P.gehalt * 1.05 WHERE PersId IN ( SELECT PersId FROM test2 ) DROP TABLE test2; 

要么

 UPDATE Pers P, ( SELECT PersId FROM pers p WHERE ( chefID IS NOT NULL OR gehalt < ( SELECT MAX ( gehalt * 1.05 ) FROM pers MA WHERE MA.chefID = p.chefID ) ) ) t SET P.gehalt = P.gehalt * 1.05 WHERE p.PersId = t.PersId 

从子查询中创build一个临时表(tempP)

 UPDATE pers P SET P.gehalt = P.gehalt * 1.05 WHERE P.persID IN ( SELECT tempP.tempId FROM ( SELECT persID as tempId FROM pers P WHERE P.chefID IS NOT NULL OR gehalt < (SELECT ( SELECT MAX(gehalt * 1.05) FROM pers MA WHERE MA.chefID = MA.chefID) AS _pers ) ) AS tempP ) 

我已经引入了一个单独的名称(别名),并给临时表的“persID”列添加一个新名称

在Mysql中,不能通过子查询来更新同一个表。

您可以分两部分查询,或者做

  UPDATE TABLE_A AS A
  INNER JOIN TABLE_A AS B ON A.field1 = B.field1
  SET field2 =? 

这很简单。 例如,而不是写作:

 INSERT INTO x (id, parent_id, code) VALUES ( NULL, (SELECT id FROM x WHERE code='AAA'), 'BBB' ); 

你应该写

 INSERT INTO x (id, parent_id, code) VALUES ( NULL, (SELECT t.id FROM (SELECT id, code FROM x) t WHERE t.code='AAA'), 'BBB' ); 

或类似的。

BlueRaja发布的方法很慢我修改它,因为我正在使用从表中删除重复项。 如果它可以帮助任何人与大表原始查询

 delete from table where id not in (select min(id) from table group by field 2) 

这需要更多时间:

 DELETE FROM table where ID NOT IN( SELECT MIN(t.Id) from (select Id,field2 from table) AS t GROUP BY field2) 

更快的解决scheme

 DELETE FROM table where ID NOT IN( SELECT x.Id from (SELECT MIN(Id) as Id from table GROUP BY field2) AS t) 

如果您正在尝试从tableA中读取fieldA并将其保存在同一个表的fieldB上,那么当fieldc = fieldd时,您可能需要考虑这一点。

 UPDATE tableA, tableA AS tableA_1 SET tableA.fieldB= tableA_1.filedA WHERE (((tableA.conditionFild) = 'condition') AND ((tableA.fieldc) = tableA_1.fieldd)); 

当条件字段符合您的条件时,以上代码将fieldA中的值复制到fieldB。 这也适用于ADO(例如访问)

来源:尝试自己

就像参考一样,您也可以使用Mysqlvariables来保存临时结果,例如:

 SET @v1 := (SELECT ... ); UPDATE ... SET ... WHERE x=@v1; 

https://dev.mysql.com/doc/refman/5.7/en/user-variables.html