Estou tentando fazer uma 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 você provavelmente pode dizer, quero excluir a relação dos pais com 1015 se o mesmo tid tiver outros pais. No entanto, isso me resulta em um erro de sintaxe:
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
Eu verifiquei a documentação e executei a subconsulta por si só, e parece que tudo deu certo. Alguém consegue descobrir o que está errado aqui?
Atualização : conforme respondido abaixo, o MySQL não permite que a tabela da qual você está excluindo seja usada em uma subconsulta para a condição.
DELETE t FROM table t ...
Respostas:
Você não pode especificar a tabela de destino para exclusão.
Uma solução alternativa
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);
fonte
Para outros que encontram esta questão procurando excluir ao usar uma subconsulta, deixo este exemplo para superar o MySQL (mesmo que algumas pessoas pareçam pensar que isso não pode ser feito):
DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar');
apresentará um erro:
ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
No entanto, esta consulta:
DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar') x);
vai funcionar bem:
Envolva sua subconsulta em uma subconsulta adicional (aqui denominada x) e o MySQL fará o que você pedir.
fonte
e
) em um DELETE e em seu sub-SELECT. Nós podemos , no entanto usar uma sub-sub-SELECT para criar uma tabela temporária (x
) e uso que para a sub-SELECT.O alias deve ser incluído após a
DELETE
palavra-chave: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 );
fonte
Você precisa se referir ao alias novamente na instrução delete, como:
DELETE th FROM term_hierarchy AS th ....
Conforme descrito aqui na documentação do MySQL.
fonte
delete from your_table as t1 where t1.id in(select t2.id from your_table t2);
o que você conseguiu?Currently, you cannot delete from a table and select from the same table in a subquery.
dev.mysql.com/doc/refman/5.5/en/delete.htmlAbordei isso de uma maneira um pouco diferente e funcionou para mim;
Eu precisava remover
secure_links
da minha tabela que fazia referência àconditions
tabela onde não havia mais linhas de condição restantes. Um script de manutenção basicamente. Isso me deu o erro - Você não pode especificar a tabela de destino para exclusão.Procurando aqui por inspiração, eu vim com a consulta abaixo e ela funciona muito bem. Isso ocorre porque ele cria uma tabela temporária
sl1
que é usada como referência para o 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 mim.
fonte
A cláusula "in" na exclusão não é ... onde, extremamente ineficiente, se houver um grande número de valores retornados da subconsulta? Não tenho certeza por que você não faria apenas a junção interna (ou direita) de volta à tabela original da subconsulta no ID para excluir, em vez de usar o "in (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)
E talvez seja respondido no "MySQL não permite", no entanto, está funcionando bem para mim, desde que eu tenha certeza de esclarecer completamente o que excluir (DELETE T FROM Target AS T). Excluir com Join no MySQL esclarece o problema DELETE / JOIN.
fonte
Se você quiser fazer isso com 2 consultas, você sempre pode fazer algo semelhante a isto:
1) pegar ids da mesa com:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...
Em seguida, copie o resultado com mouse / teclado ou linguagem de programação para XXX abaixo:
2) DELETE FROM your_table WHERE id IN ( XXX )
Talvez você pudesse fazer isso em uma consulta, mas é o que eu prefiro.
fonte
@CodeReaper, @BennyHill: Funciona conforme o esperado.
No entanto, eu me pergunto a complexidade de tempo para ter milhões de linhas na tabela? Aparentemente, demorou
5ms
para ser executado por ter 5k registros em uma tabela indexada corretamente.Minha consulta:
SET status = '1' WHERE id IN ( SELECT id FROM ( SELECT c2.id FROM clusters as c2 WHERE c2.assign_to_user_id IS NOT NULL AND c2.id NOT IN ( SELECT c1.id FROM clusters AS c1 LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id WHERE ft.slug = 'closed' ) ) x)``` Or is there something we can improve on my query above?
fonte
você pode usar o alias desta forma na instrução delete
DELETE th.* FROM term_hierarchy th INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th.parent = 1015;
fonte