2010-07-26 15 views
85

Tôi đang cố gắng xóa khỏi một vài bảng cùng một lúc. Tôi đã làm một chút nghiên cứu, và đã đưa ra với điều nàyLàm thế nào để xóa khỏi nhiều bảng trong MySQL?

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

Tuy nhiên, tôi nhận được lỗi này

của router Database_Exception [1064]: Bạn có một lỗi trong cú pháp SQL của bạn; kiểm tra hướng dẫn tương ứng với phiên bản máy chủ MySQL của bạn cho đúng cú pháp để sử dụng gần 'p, pets_activities pa ...

Tôi chưa bao giờ thực hiện một bảng chéo xóa trước đó, vì vậy tôi thiếu kinh nghiệm và mắc kẹt cho hiện nay!

Tôi đang làm gì sai?

Trả lời

153

Sử dụng JOIN trong tuyên bố DELETE.

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 

Hoặc bạn có thể sử dụng ...

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 

... để xóa chỉ từ pets_activities

Xem http://dev.mysql.com/doc/refman/5.0/en/delete.html

Đối với bảng duy nhất xóa, nhưng với toàn vẹn tham chiếu, có nhiều cách khác để thực hiện với EXISTS, NOT EXISTS, IN, NOT IN, vv Nhưng cái ở trên nơi bạn chỉ định từ đó các bảng cần xóa với một bí danh trước mệnh đề FROM có thể đưa bạn ra khỏi một vài điểm khá chặt chẽ dễ dàng hơn. Tôi có xu hướng tiếp cận với một EXISTS trong 99% các trường hợp và sau đó có 1% trong đó cú pháp MySQL này lấy ngày.

+5

Tôi đã thử điều này "xóa tất cả trong 1 truy vấn" với việc tham gia 6 bảng lớn (tất cả mọi người khoảng ~ 15k hàng) và truy vấn mất 155 giây để xóa 63 hàng trong 6 bảng: O – techouse

+1

@cadman Đây là câu trả lời đúng; có thể có những lý lẽ chống lại việc sử dụng nó, nhưng nó rất hữu ích vào dịp –

+1

+1 Tôi đồng ý rằng điều này trong câu trả lời đúng, vì câu hỏi không phải là "bạn nên" mà là "làm thế nào để". Tuy nhiên, tôi sẽ quan tâm đến việc nghe về 1% vì tôi không thể nghĩ ra một tình huống duy nhất mà điều này sẽ được ưa thích hơn. –

17

Vì đây dường như là một phụ huynh/mối quan hệ con đơn giản giữa petspets_activities, bạn sẽ tốt hơn khi tạo ràng buộc khóa ngoài của bạn bằng cách xóa thác.

Bằng cách đó, khi một hàng pets bị xóa, pets_activities hàng được liên kết với nó cũng sẽ tự động bị xóa.

Sau đó truy vấn của bạn sẽ trở thành một đơn giản:

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

Xóa các thác đang mời những tai nạn khủng khiếp. –

+0

Cảm ơn Paxdiablo, tôi không chắc chắn làm thế nào để làm điều này được nêu ra trong MySQL nhưng tôi sẽ xem xét nó. – alex

+2

@Erick, miễn là bạn đã thiết lập tính toàn vẹn tham chiếu, việc xóa tầng có thể không gây ra nhiều rắc rối hơn là xóa riêng của nó. Chúng ta đã biết rằng 'pa' là một con thích hợp của' p' do ánh xạ 'id/pet_id'. – paxdiablo

2

Tôi không có một cơ sở dữ liệu mysql để thử nghiệm trên vào lúc này, nhưng bạn đã cố gắng xác định những gì để xóa trước khi từ khoản? Ví dụ:

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` 

Tôi nghĩ cú pháp bạn sử dụng được giới hạn trong các phiên bản mới hơn của mysql.

+1

Truy vấn đó được thực hiện thành công, tuy nhiên, nó không xóa bất kỳ hàng nào (nhưng tôi tin rằng nó nên có). – alex

12

Sử dụng này

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

hoặc

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

Đẹp - có vẻ tốt hơn và dễ hơn sử dụng JOIN. Đó là giải pháp tốt nhất tôi thấy ở đây .. cảm ơn! – gnB

+1

Tìm thấy một tài liệu tham khảo tốt cho việc sử dụng này và một vài tùy chọn khác tại http://www.mysqltutorial.org/mysql-delete-statement.aspx –

0

Để bất cứ ai đọc sách này vào năm 2017, đây là cách tôi đã làm điều gì đó tương tự.

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 

Nói chung, để xóa các hàng khỏi nhiều bảng, cú pháp tôi theo được đưa ra dưới đây. Giải pháp dựa trên giả định rằng có một số mối quan hệ giữa hai bảng.

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