CSc*_*ulz 353 mysql sql mysql-error-1093
我有一个简单的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);
Run Code Online (Sandbox Code Playgroud)
我试图运行以下更新,但我只得到错误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
))
Run Code Online (Sandbox Code Playgroud)
我搜索了错误,并在http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html页面的mysql中找到,但它对我没有帮助.
我该怎么做才能纠正sql查询?
Blu*_*eft 726
问题在于,无论出于什么原因,MySQL都不允许你编写这样的查询:
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM myTable
INNER JOIN ...
)
Run Code Online (Sandbox Code Playgroud)
也就是说,如果你正在做一个UPDATE/ INSERT/ DELETE桌子上,你不能引用表内查询(您可以但是从外部表引用一个字段...)
该解决方案是更换的情况下myTable在子查询中使用(SELECT * FROM myTable),这样的
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM (SELECT * FROM myTable) AS something
INNER JOIN ...
)
Run Code Online (Sandbox Code Playgroud)
这显然会导致必要的字段被隐式复制到临时表中,所以它是允许的.
我在这里找到了解决方案.该文的说明:
你不想只是
SELECT * FROM table在现实生活中的子查询中; 我只是想让这些例子保持简单.实际上,您应该只在最内层查询中选择所需的列,并添加一个goodWHERE子句来限制结果.
Mic*_*sov 53
您可以分三步完成:
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
)
)
Run Code Online (Sandbox Code Playgroud)
...
UPDATE pers P
SET P.gehalt = P.gehalt * 1.05
WHERE PersId
IN (
SELECT PersId
FROM test2
)
DROP TABLE test2;
Run Code Online (Sandbox Code Playgroud)
要么
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
Run Code Online (Sandbox Code Playgroud)
Yua*_*tao 25
在Mysql中,您不能通过子查询同一个表来更新一个表.
您可以将查询分为两部分,或者执行
UPDATE TABLE_A AS A INNER JOIN TABLE_A AS B ON A.field1 = B.field1 SET field2 = ?
Bud*_*dda 23
从子查询创建临时表(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
)
Run Code Online (Sandbox Code Playgroud)
我已经引入了一个单独的名称(别名),并为临时表的'persID'列提供了一个新名称
Dar*_*ide 18
这很简单.例如,而不是写:
INSERT INTO x (id, parent_id, code) VALUES (
NULL,
(SELECT id FROM x WHERE code='AAA'),
'BBB'
);
Run Code Online (Sandbox Code Playgroud)
你应该写
INSERT INTO x (id, parent_id, code)
VALUES (
NULL,
(SELECT t.id FROM (SELECT id, code FROM x) t WHERE t.code='AAA'),
'BBB'
);
Run Code Online (Sandbox Code Playgroud)
或类似的.
Har*_*Das 15
MySQL 不允许同时从表中进行选择并在同一个表中进行更新。但总有一个解决方法:)
这不行>>>>
UPDATE table1 SET col1 = (SELECT MAX(col1) from table1) WHERE col1 IS NULL;
Run Code Online (Sandbox Code Playgroud)
但这有效>>>>
UPDATE table1 SET col1 = (SELECT MAX(col1) FROM (SELECT * FROM table1) AS table1_new) WHERE col1 IS NULL;
Run Code Online (Sandbox Code Playgroud)
Aja*_*ak6 11
BlueRaja发布的方法很慢我修改了它,因为我用来删除表中的重复项.万一它可以帮助任何人使用大表原始查询
delete from table where id not in (select min(id) from table group by field 2)
Run Code Online (Sandbox Code Playgroud)
这需要更多时间:
DELETE FROM table where ID NOT IN(
SELECT MIN(t.Id) from (select Id,field2 from table) AS t GROUP BY field2)
Run Code Online (Sandbox Code Playgroud)
更快的解决方案
DELETE FROM table where ID NOT IN(
SELECT x.Id from (SELECT MIN(Id) as Id from table GROUP BY field2) AS t)
Run Code Online (Sandbox Code Playgroud)
MariaDB 从 10.3.x 开始提升了这一点(包括DELETE和UPDATE):
从 MariaDB 10.3.2 开始,UPDATE 语句可能具有相同的源和目标。
在 MariaDB 10.3.1 之前,以下 UPDATE 语句不起作用:
Run Code Online (Sandbox Code Playgroud)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 开始,语句成功执行:
Run Code Online (Sandbox Code Playgroud)UPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1);
在 MariaDB 10.3.1 之前,无法从具有相同源和目标的表中删除。从 MariaDB 10.3.1 开始,这现在是可能的。例如:
Run Code Online (Sandbox Code Playgroud)DELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE b.c2=0);
作为参考,您还可以使用Mysql变量保存临时结果,例如:
SET @v1 := (SELECT ... );
UPDATE ... SET ... WHERE x=@v1;
Run Code Online (Sandbox Code Playgroud)
https://dev.mysql.com/doc/refman/5.7/zh-CN/user-variables.html