Xóa khỏi hai bảng trong một truy vấn


82

Tôi có hai bảng trong MySQL

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

Bây giờ nếu tôi muốn xóa khỏi bảng tin nhắn thì không sao cả. Nhưng khi tôi xóa tin nhắn bằng messageid, bản ghi vẫn tồn tại trên usersmessage và tôi phải xóa khỏi hai bảng này cùng một lúc.

Tôi đã sử dụng truy vấn sau:

DELETE FROM messages LEFT JOIN usersmessages USING(messageid) WHERE messageid='1' ; 

Sau đó tôi kiểm tra

   DELETE FROM messages , usersmessages 
   WHERE messages.messageid = usersmessages.messageid 
   and messageid='1' ; 

Nhưng hai truy vấn này không hoàn thành nhiệm vụ này.

Câu trả lời:


135

Bạn không thể chỉ tách chúng bằng dấu chấm phẩy?

Delete from messages where messageid = '1';
Delete from usersmessages where messageid = '1'

HOẶC LÀ

Chỉ cần sử dụng INNER JOINnhư bên dưới

DELETE messages , usersmessages  FROM messages  INNER JOIN usersmessages  
WHERE messages.messageid= usersmessages.messageid and messages.messageid = '1'

1
Điều gì xảy ra nếu tôi muốn đặt mã này trong một vòng lặp? tôi biết tôi hoàn toàn có thể đặt dấu chấm phẩy.
mehdi

1
Nó có thể được đặt trong một vòng lặp. Bạn có thể làm điều đó theo chương trình và gửi id tin nhắn dưới dạng tham số. Miễn là bạn không tiếp tục gửi nó cùng một id, nó sẽ không thực hiện xóa nhiều lần.
Eric

4
Nếu bạn thực hiện điều này trong hai truy vấn, bạn thực sự nên kết thúc điều này trong một giao dịch. Đối với việc chạy các truy vấn xóa trong một vòng lặp, tốt hơn hết bạn nên xây dựng một truy vấn duy nhất để thực hiện tất cả các thao tác xóa.
JohnFx

1
Thanh toán một ví dụ về truy vấn xóa với tham gia bennadel.com/blog/...
Babar

19
Không hoạt động với SQL Server: Cú pháp không chính xác gần ','.
Paul-Sebastian Manole

44
DELETE a.*, b.* 
FROM messages a 
LEFT JOIN usersmessages b 
ON b.messageid = a.messageid 
WHERE a.messageid = 1

dịch: xóa khỏi các thư trong bảng mà messageid = 1, nếu uersmessages trong bảng có messageid = messageid của các thông báo trong bảng , hãy xóa hàng đó của bảng uersmessages .


nhận xét cho tất cả: như được hiển thị trong ví dụ này, điều quan trọng là phải chỉ định xóa sẽ hoạt động trong bảng nào. Bài đăng tuyệt vời @angry_kiwi
Raphael_b

Tôi vừa thay đổi thứ tự, TỪ usersmessages b LEFT JOIN thông điệp một
Pablo

15

Bạn nên tạo một FOREIGN KEYvới ON DELETE CASCADE:

ALTER TABLE usersmessages
ADD CONSTRAINT fk_usermessages_messageid
FOREIGN KEY (messageid)
REFERENCES messages (messageid)
ON DELETE CASCADE

hoặc làm điều đó bằng cách sử dụng hai truy vấn trong một giao dịch:

START TRANSACTION;;

DELETE
FROM    usermessages
WHERE   messageid = 1

DELETE
FROM    messages
WHERE   messageid = 1;

COMMIT;

Tuy nhiên, giao dịch chỉ ảnh hưởng đến InnoDBcác bảng.


3
Bạn có thể xóa khỏi nhiều bảng trong một truy vấn! dev.mysql.com/doc/refman/5.0/en/delete.html
txwikinger

vâng bạn có thể! Nhưng đối với tôi ... nó dễ dàng hơn để làm những gì câu trả lời của tôi đã nói.
Eric

Tôi đã thêm tầng trên một bàn tương tự của tôi. Khi tôi cố gắng chỉ xóa khỏi 1 bảng, nó đã xóa bản ghi và khiến bảng có liên quan bị mồ côi. Ràng buộc là gì?
barfoon

@barfoon: có phải bàn của bạn InnoDBkhông?
Quassnoi

@Quassnoi Rất tiếc! Tôi chắc chắn đã nghĩ nó là như vậy, thật là ngu ngốc. Tất cả các bảng đều là MyISAM. Tôi có thể thay đổi tất cả chúng một cách nhanh chóng với dữ liệu trong đó không? Hoặc là có vấn đề với điều đó?
barfoon

7

Bạn có hai lựa chọn:

Đầu tiên, hãy thực hiện hai câu lệnh bên trong một giao dịch:

BEGIN;
  DELETE FROM messages WHERE messageid = 1;
  DELETE FROM usermessages WHERE messageid = 1;
COMMIT;

Hoặc, bạn có thể thiết lập ON DELETE CASCADE bằng khóa ngoại. Đây là cách tiếp cận tốt hơn.

CREATE TABLE parent (
  id INT NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE child (
  id INT, parent_id INT,
  FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
);

Bạn có thể đọc thêm về BẬT XÓA CASCADE tại đây .


7

không cần JOINS:

DELETE m, um FROM messages m, usersmessages um

WHERE m.messageid = 1 

AND m.messageid = um.messageid 

6
DELETE message.*, usersmessage.* from users, usersmessage WHERE message.messageid=usersmessage.messageid AND message.messageid='1'

6

OP chỉ thiếu bí danh bảng sau khi xóa

DELETE t1, t2 
FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id 
WHERE t1.id = some_id

3
Cảm ơn câu trả lời của bạn. Sẽ hữu ích hơn nếu bạn cố gắng giải thích tại sao điều này sẽ hoạt động và tại sao giải pháp OP lại không.
DdW

1

Vui lòng thử cái này

DELETE FROM messages,usersmessages

USING messages

INNER JOIN usermessages on (messages.messageid = usersmessages.messageid)

WHERE messages.messsageid='1'

0

Thử đi..

DELETE a.*, b.*  
FROM table1 as a, table2 as b  
WHERE a.id=[Your value here] and b.id=[Your value here]

Tôi để idnhư một cột mẫu.

Rất vui vì điều này có ích. :)


Để asterikses ( *) được hiển thị đúng cách, bạn cần phải thụt lề truy vấn với 4 dấu cách phía trước nó.
Al.G.

0

Bạn cũng có thể sử dụng như thế này, để xóa giá trị cụ thể khi cả hai cột có 2 hoặc nhiều cột giống nhau.

DELETE project , create_test  FROM project INNER JOIN create_test
WHERE project.project_name='Trail' and  create_test.project_name ='Trail' and project.uid= create_test.uid = '1';

0

có một cách khác không được đề cập ở đây (tôi chưa kiểm tra đầy đủ hiệu suất của nó), bạn có thể đặt mảng cho tất cả các bảng -> hàng bạn muốn xóa như bên dưới

// set your tables array
$array = ['table1', 'table2', 'table3'];


// loop through each table
for($i = 0; $i < count($array); $i++){

 // get each single array
 $single_array = $array[$i];

 // build your query
 $query = "DELETE FROM $single_array WHERE id = 'id'";

 // prepare the query and get the connection
 $data = con::GetCon()->prepare($query);

 // execute the action
 $data->execute();
}

thì bạn có thể chuyển hướng người dùng đến trang chủ.

header('LOCATION:' . $home_page);

hy vọng điều này sẽ giúp ai đó :)

Cảm ơn


Điều này cũng có thể giúp ai đó ... có vẻ giống như PHP, tôi không nghĩ rằng điều đó nhất thiết phải nằm trong phạm vi của câu hỏi :)
Tom Bush
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.