No puede especificar la tabla de destino para la actualización en la cláusula FROM
Tengo una tabla MySQL simple:
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);
Intenté ejecutar la siguiente actualización, pero solo aparece el error 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
))
Busqué el error y lo encontré en la siguiente página de MySQL http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html , pero no me ayuda.
¿Qué debo hacer para corregir la consulta SQL?
El problema es que MySQL, por alguna razón tonta, no te permite escribir consultas como esta:
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM myTable
INNER JOIN ...
)
Es decir, si está haciendo un // UPDATE
en una tabla, no puede hacer referencia a esa tabla en una consulta interna ( sin embargo, puede hacer referencia a un campo de esa tabla externa...)INSERT
DELETE
La solución es reemplazar la instancia de myTable
en la subconsulta con (SELECT * FROM myTable)
, así
UPDATE myTable
SET myTable.A =
(
SELECT B
FROM (SELECT * FROM myTable) AS something
INNER JOIN ...
)
Aparentemente, esto hace que los campos necesarios se copien implícitamente en una tabla temporal, por lo que está permitido.
Encontré esta solución aquí . Una nota de ese artículo:
No querrás simplemente estar
SELECT * FROM table
en la subconsulta en la vida real; Sólo quería mantener los ejemplos simples. En realidad, solo debería seleccionar las columnas que necesita en esa consulta más interna y agregar una buenaWHERE
cláusula para limitar los resultados también.
Puedes hacer esto en tres pasos:
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;
o
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
Crear una tabla temporal (tempP) a partir de una subconsulta
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
)
Introduje un nombre (alias) separado y le di un nuevo nombre a la columna 'persID' para la tabla temporal
En Mysql, no se puede actualizar una tabla realizando subconsultas en la misma tabla.
Puede separar la consulta en dos partes, o hacer
ACTUALIZAR TABLA_A COMO A UNIÓN INTERNA TABLE_A COMO B EN A.campo1 = B.campo1 ESTABLECER campo2 =?