Usuń z dwóch tabel w jednym zapytaniu

84

Mam dwie tabele w MySQL

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

Teraz, jeśli chcę usunąć z tabeli wiadomości, wszystko jest w porządku. Ale kiedy usuwam wiadomość według messageid, rekord nadal istnieje na usermessage i muszę usunąć z tych dwóch tabel naraz.

Użyłem następującego zapytania:

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

Potem testuję

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

Ale te dwa zapytania nie wykonują tego zadania.

Mehdi
źródło

Odpowiedzi:

137

Nie możesz po prostu oddzielić ich średnikiem?

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

LUB

Po prostu użyj INNER JOINjak poniżej

DELETE messages , usersmessages  FROM messages  INNER JOIN usersmessages  
WHERE messages.messageid= usersmessages.messageid and messages.messageid = '1'
Eric
źródło
1
co się stanie, jeśli chcę umieścić ten kod w pętli? Wiem, że absolutnie mogę wstawić średnik.
Mehdi
1
Można go zapętlić. Możesz to zrobić programowo i wysłać identyfikator wiadomości jako parametr. Dopóki nie będziesz wysyłać tego samego identyfikatora, nie usuniesz go w kółko.
Eric
4
Jeśli zrobisz to w dwóch zapytaniach, naprawdę powinieneś zawrzeć to w transakcji. Jeśli chodzi o uruchamianie zapytań usuwających w pętli, lepiej jest sformułować jedno zapytanie, aby wykonać wszystkie usunięcia.
JohnFx
1
Sprawdź
Babar
21
Nie działa z SQL Server: nieprawidłowa składnia w pobliżu „,”.
Paul-Sebastian Manole
45
DELETE a.*, b.* 
FROM messages a 
LEFT JOIN usersmessages b 
ON b.messageid = a.messageid 
WHERE a.messageid = 1

translacja: usuń z tabeli wiadomości, gdzie identyfikator wiadomości = 1, jeśli tabela uersmessages ma identyfikator wiadomości = identyfikator wiadomości z tabeli , usuń ten wiersz tabeli uersmessages .

zły kiwi
źródło
komentarz dla wszystkich: jak pokazano w tym przykładzie, ważne jest, aby określić, w której tabeli ma działać usuwanie. Świetny post @angry_kiwi
Raphael_b
Miałem tylko zmienić kolejność, Z wiadomości użytkowników b LEFT JOIN wiadomości a
Pablo
15

Powinieneś albo utworzyć FOREIGN KEYz ON DELETE CASCADE:

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

lub zrób to za pomocą dwóch zapytań w transakcji:

START TRANSACTION;;

DELETE
FROM    usermessages
WHERE   messageid = 1

DELETE
FROM    messages
WHERE   messageid = 1;

COMMIT;

Transakcja dotyczy jednak tylko InnoDBtabel.

Quassnoi
źródło
3
Państwo może usunąć z wielu tabel w jednym zapytaniu! dev.mysql.com/doc/refman/5.0/en/delete.html
txwikinger
tak, możesz! Ale dla mnie ... łatwiej jest zrobić to, co mówi moja odpowiedź.
Eric
Dodałem kaskadę na podobnym stole. Kiedy próbowałem usunąć tylko z 1 tabeli, usunął rekord i pozostawił powiązany z nim osierocony. Po co to ograniczenie?
barfoon
@barfoon: czy twój stół InnoDB?
Quassnoi
@Quassnoi Ups! Zdecydowanie myślałem, że to była głupota. Wszystkie tabele to MyISAM. Czy mogę zmienić je wszystkie w locie z danymi w nich? Czy są z tym jakieś problemy?
barfoon
7

Masz dwie możliwości:

Najpierw wykonaj dwie instrukcje wewnątrz transakcji:

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

Lub możesz ustawić ON DELETE CASCADE z kluczem obcym. To jest lepsze podejście.

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
);

Możesz przeczytać więcej o ON DELETE CASCADE tutaj .

Mike Trpcic
źródło
7

nie ma potrzeby ŁĄCZENIA:

DELETE m, um FROM messages m, usersmessages um

WHERE m.messageid = 1 

AND m.messageid = um.messageid 
Fred Yates
źródło
6
DELETE message.*, usersmessage.* from users, usersmessage WHERE message.messageid=usersmessage.messageid AND message.messageid='1'
johan
źródło
6

W OP brakuje tylko aliasów tabeli po usunięciu

DELETE t1, t2 
FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id 
WHERE t1.id = some_id
Mark Angelo Pascual
źródło
3
Dzięki za odpowiedź. Byłoby bardziej pomocne, gdybyś spróbował wyjaśnić, dlaczego to zadziałało i dlaczego rozwiązanie PO nie zadziałało.
DdW
1

Spróbuj tego, proszę

DELETE FROM messages,usersmessages

USING messages

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

WHERE messages.messsageid='1'
Amit
źródło
0

Spróbuj tego..

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

Podałem idjako próbną kolumnę.

Cieszę się, że to pomaga. :)

John Oliver Amurao
źródło
Aby asterikses ( *) były renderowane poprawnie, musisz wciąć zapytanie z 4 spacjami przed nim.
Al.G.
0

Możesz również użyć w ten sposób, aby usunąć określoną wartość, gdy obie kolumny mają 2 lub wiele takich samych nazw kolumn.

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';
Vidya
źródło
0

jest inny sposób, o którym tutaj nie wspomniano (nie testowałem jeszcze w pełni jego wydajności), możesz ustawić tablicę dla wszystkich tabel -> wiersze, które chcesz usunąć, jak poniżej

// 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();
}

wtedy możesz przekierować użytkownika na stronę główną.

header('LOCATION:' . $home_page);

mam nadzieję, że to komuś pomoże :)

Dzięki

Midz Elwekil
źródło
To może komuś pomóc ... chociaż wygląda jak PHP, nie sądzę, żeby to koniecznie mieściło się w zakresie pytania :)
Tom Bush