Como excluir de várias tabelas no MySQL?


116

Estou tentando excluir algumas tabelas de uma vez. Eu fiz um pouco de pesquisa e descobri este

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

No entanto, estou recebendo este erro

Não capturada Database_Exception [1064]: você tem um erro na sintaxe SQL; verifique o manual que corresponde à versão do seu servidor MySQL para a sintaxe correta para usar próximo a 'p, pets_activitiespa ...

Eu nunca fiz uma exclusão de tabela cruzada antes, então sou inexperiente e estou preso por agora!

O que estou fazendo de errado?

Respostas:


204

Use um JOINna DELETEdeclaração.

DELETE p, pa
      FROM pets p
      JOIN pets_activities pa ON pa.id = p.pet_id
     WHERE p.order > :order
       AND p.pet_id = :pet_id

Alternativamente, você pode usar ...

DELETE pa
      FROM pets_activities pa
      JOIN pets p ON pa.id = p.pet_id
 WHERE p.order > :order
   AND p.pet_id = :pet_id

... para excluir apenas de pets_activities

Veja isso .

Para exclusões de mesa única, mas com integridade referencial, existem outras maneiras de fazer com EXISTS, NOT EXISTS, IN, NOT INe etc. Mas a uma acima de onde você especificar de quais tabelas para apagar com um alias antes da FROMcláusula pode tirá-lo de alguns apertado bastante manchas mais facilmente. Costumo chegar a um EXISTSem 99% dos casos e, em seguida, é o 1% em que essa sintaxe do MySQL leva o dia.


7
Eu tentei "deletar tudo em 1 consulta" juntando 6 tabelas grandes (todos com aproximadamente 15 mil linhas) e a consulta levou 155 segundos para deletar 63 linhas em 6 tabelas: O
Klemen Tušar

1
@cadman Esta é a resposta certa; pode haver argumentos contra o seu uso, mas é muito útil ocasionalmente
Simon Christian

1
1 Concordo que isso é a resposta certa, já que a pergunta não era "você deveria", mas "como fazer". No entanto, eu estaria interessado em ouvir sobre o 1%, porque não consigo pensar em uma única situação em que isso seria preferido.
Erick Robertson

2
@techouse, você se inscreveu e filtrou índices? 15k x 15k x 15k x 15k 15k x 15k é 11 milhões. Demorou da SELECTmesma forma?
Paul Draper

6
Você também pode usar LEFT JOIN, que é útil se a segunda tabela não tiver entradas correspondentes, caso contrário, nada será excluído.
Lexib0y

20

Visto que esta parece ser uma relação pai / filho simples entre petse pets_activities, seria melhor criar sua restrição de chave estrangeira com uma cascata de exclusão.

Dessa forma, quando uma petslinha é excluída, as pets_activitieslinhas associadas a ela também são excluídas automaticamente.

Então, sua consulta se torna simples:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id

3
@Erick, desde que você tenha configurado a integridade referencial, exclusões em cascata não podem causar mais problemas do que excluir por conta própria. Já sabemos que paé um filho próprio pdevido ao id/pet_idmapeamento.
paxdiablo

14
Bem, vocês têm suas próprias ideias, mas parece que estão descontando muito do poder do DBMS '. As exclusões em cascata fazem parte do gerenciamento de dados tanto quanto gatilhos, procedimentos armazenados ou restrições e só são perigosas se você não souber o que está fazendo. Ainda assim, não vou discutir mais o ponto, teremos apenas que concordar em discordar.
paxdiablo

8
Erick, agora você despertou meu interesse. Como você garante a integridade dos dados dentro do banco de dados sem restrições?
paxdiablo

4
@Erick disse: "Eu também não uso gatilhos, procedimentos armazenados ou restrições." Ah, você usa o Excel. :-)
james.garriss

4
Eu só quero acompanhar isso. Eu mudei minha posição sobre a exclusão de cascatas nesta situação. Eu fiz parte de um novo ambiente SQL que os usava, e os usava bem e eles eram muito organizados. Nesse sistema, funcionou muito bem ter essas cascatas no lugar. Certamente evitava dados órfãos e não era perigoso. O problema é que todos que trabalham com o banco de dados precisam entender como usá-los com segurança. Mas sempre há riscos quando os desenvolvedores juniores estão fazendo alterações no banco de dados sem supervisão.
Erick Robertson

14

Usa isto

DELETE FROM `articles`, `comments` 
USING `articles`,`comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

ou

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

1
Encontrou uma boa referência para usar isso e algumas outras opções em mysqltutorial.org/mysql-delete-statement.aspx
Mavelo

3

Não tenho um banco de dados mysql para testar no momento, mas você tentou especificar o que excluir antes da cláusula from? Por exemplo:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

Acho que a sintaxe que você usou é limitada a versões mais recentes do mysql.


1
Essa consulta foi executada com sucesso, no entanto, não excluiu nenhuma linha (mas acredito que deveria).
alex

2

A sintaxe parece certa para mim ... tente alterá-la para usar INNER JOIN...

Dê uma olhada nisso .


7
Pena que você não incluiu a solução real, porque o link está correto!
mycroes

1

Para quem estiver lendo isso em 2017, é assim que fiz algo semelhante.

DELETE pets, pets_activities FROM pets inner join pets_activities
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id

Geralmente, para excluir linhas de várias tabelas, a sintaxe que sigo é fornecida a seguir. A solução parte do pressuposto de que existe alguma relação entre as duas tabelas.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.