您不能在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;