我有一个简单的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
))

我搜索了这个错误,并从mysql下面的页面http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html找到,但它没有帮助我。

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


当前回答

问题是MySQL,不管出于什么愚蠢的原因,不允许你写这样的查询:

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

也就是说,如果你正在对一个表执行UPDATE/INSERT/DELETE操作,你不能在内部查询中引用该表(但是你可以引用外部表中的字段…)


解决方案是用(SELECT * FROM myTable)替换子查询中的myTable实例,如下所示

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

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

我找到了这个解。那篇文章的注释如下:

在实际的子查询中,你不希望只是SELECT * FROM表;我只是想让例子简单些。实际上,您应该只选择最里面的查询中需要的列,并添加一个好的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;

or

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

这很简单。例如,不要写:

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'
);

或类似的。

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

您可以将查询分成两部分,也可以这样做

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

MySQL不允许同时从一个表中进行选择和更新。但总有一个变通办法:)

这行不通>>>>

UPDATE table1 SET col1 = (SELECT MAX(col1) from table1) WHERE col1 IS NULL;

但这是可行的>>>>

UPDATE table1 SET col1 = (SELECT MAX(col1) FROM (SELECT * FROM table1) AS table1_new) WHERE col1 IS NULL;

如果您试图从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(例如访问)

来源:我自己试过