stackoverflow - MySQL DELETE FROM con subconsulta como condición
mysql update delete (7)
¿No es la cláusula "in" en el delete ... where, extremadamente ineficiente, si va a haber una gran cantidad de valores devueltos desde la subconsulta? No estoy seguro de por qué no se uniría interna (o derecha) a la tabla original desde la subconsulta en la ID para eliminar, en lugar de a nosotros el "en (subconsulta)".
DELETE T FROM Target AS T
RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID)
Y tal vez se responde en el "MySQL no lo permite", sin embargo, está funcionando bien para mí siempre que me asegure de aclarar por completo qué eliminar (ELIMINAR T DE COMO AS T). Eliminar con Join en MySQL aclara el problema DELETE / JOIN.
Estoy tratando de hacer una consulta como esta:
DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015
);
Como probablemente pueda decir, quiero eliminar la relación padre a 1015 si el mismo tid tiene otros padres. Sin embargo, eso me da un error de sintaxis:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM ter'' at line 1
Revisé la documentación y ejecuté la subconsulta por sí mismo, y parece que todo está pendiente. ¿Alguien puede descubrir lo que está mal aquí?
Actualización : Como se explica a continuación, MySQL no permite que la tabla que está eliminando se use en una subconsulta para la condición.
Debe volver a consultar el alias en la declaración de eliminación, como:
DELETE th FROM term_hierarchy AS th
....
El alias se debe incluir después de la palabra clave DELETE
:
DELETE th
FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN
(
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015
);
Me acerqué a esto de una manera ligeramente diferente y funcionó para mí;
Necesitaba eliminar secure_links
de mi tabla que hacía referencia a la tabla de conditions
donde ya no quedaban filas de condiciones. Un guión de limpieza básicamente. Esto me dio el error: no puede especificar la tabla de destino para eliminar.
Así que, buscando inspiración aquí, se me ocurrió la siguiente pregunta y funciona muy bien. Esto se debe a que crea una tabla temporal sl1
que se utiliza como referencia para el DELETE.
DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN
(
SELECT
`sl1`.`link_id`
FROM
(
SELECT
`sl2`.`link_id`
FROM
`secure_links` AS `sl2`
LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job`
WHERE
`sl2`.`action` = ''something'' AND
`conditions`.`ref` IS NULL
) AS `sl1`
)
Funciona para mi.
No puede especificar la tabla de destino para eliminar.
Una solución
create table term_hierarchy_backup (tid int(10)); <- check data type
insert into term_hierarchy_backup
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015;
DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup);
Para otros que buscan eliminar esta pregunta mientras usan una subconsulta, les dejo este ejemplo para burlar a MySQL (incluso si algunas personas parecen pensar que no se puede hacer):
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM tableE
WHERE arg = 1 AND foo = ''bar'');
te dará un error:
ERROR 1093 (HY000): You can''t specify target table ''e'' for update in FROM clause
Sin embargo, esta consulta:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM (SELECT id
FROM tableE
WHERE arg = 1 AND foo = ''bar'') x);
funcionará bien
Query OK, 1 row affected (3.91 sec)
Envuelva su subconsulta en una subconsulta adicional (aquí nombrada x) y MySQL hará lo que le pida.
Si desea hacer esto con 2 consultas, siempre puede hacer algo similar a esto:
1) tomar identificadores de la mesa con:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = ''test'' ...
Luego copie el resultado con el mouse / teclado o el lenguaje de programación a XXX a continuación:
2) DELETE FROM your_table WHERE id IN ( XXX )
Tal vez podrías hacer esto en una consulta, pero esto es lo que prefiero.