我有一个简单的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
))
我搜索了错误,并在页面http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html后面的mysql中找到了错误,但它对我没有帮助。
我该怎么做才能纠正sql查询?
答案 0 :(得分:666)
问题在于,无论出于什么原因,MySQL都不允许你编写这样的查询:
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM myTable
INNER JOIN ...
)
也就是说,如果您在表上执行UPDATE
/ INSERT
/ DELETE
,则无法在内部查询中引用该表(您< strong>可以引用该外表中的字段...)
解决方案是将子查询中的myTable
实例替换为(SELECT * FROM myTable)
,就像这样
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM (SELECT * FROM myTable) AS something
INNER JOIN ...
)
这显然会导致必要的字段被隐式复制到临时表中,所以它是允许的。
我找到了这个解决方案here。该文的说明:
你不想在现实生活中的子查询中
SELECT * FROM table
;我只是想让这些例子保持简单。实际上,您应该只在最内层查询中选择所需的列,并添加一个好的WHERE
子句来限制结果。
答案 1 :(得分:52)
您可以分三步完成:
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
答案 2 :(得分:23)
在Mysql中,你不能通过子查询同一个表来更新一个表。
您可以将查询分为两部分,或者执行
UPDATE TABLE_A AS A INNER JOIN TABLE_A AS B ON A.field1 = B.field1 SET field2 = ?
答案 3 :(得分:21)
从子查询
创建临时表(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'列提供了一个新名称
答案 4 :(得分:17)
这很简单。例如,而不是写:
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'
);
或类似。
答案 5 :(得分:12)
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)
更快的解决方案
DELETE FROM table where ID NOT IN(
SELECT x.Id from (SELECT MIN(Id) as Id from table GROUP BY field2) AS t)
答案 6 :(得分:3)
如果您尝试从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(例如访问)
来源:尝试自己
答案 7 :(得分:3)
作为参考,您也可以使用Mysql Variables来保存临时结果,例如:
SET @v1 := (SELECT ... );
UPDATE ... SET ... WHERE x=@v1;
答案 8 :(得分:2)
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;
答案 9 :(得分:1)
MariaDB从10.3.x(DELETE
和UPDATE
开始)提升了这一点:
UPDATE - Statements With the Same Source and Target
从MariaDB 10.3.2开始,UPDATE语句可能具有相同的源和目标。
在MariaDB 10.3.1之前,以下UPDATE语句不起作用:
UPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1); ERROR 1093 (HY000): Table 't1' is specified twice, both as a target for 'UPDATE' and as a separate source for data
从MariaDB 10.3.2开始,语句成功执行:
UPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1);
DELETE - Same Source and Target Table
在MariaDB 10.3.1之前,无法从具有相同源和目标的表中删除。从MariaDB 10.3.1开始,现在可以实现。例如:
DELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE b.c2=0);
答案 10 :(得分:0)
其他变通办法包括在子查询中使用SELECT DISTINCT或LIMIT,尽管它们对实现的影响不那么明显。这对我有用
答案 11 :(得分:-1)
在没有ID的地方更新x设置available_material_id = null(从x那里选择id,其中Additional_info = 1);
-- use left join ----
update x left join
x xx
on x.id = xx.id and xx.additional_info = 1
set available_material_id = null
where xx.id is null;