Удалить из двух таблиц одним запросом


84

У меня две таблицы в MySQL

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

Теперь, если я хочу удалить из таблицы сообщений, ничего страшного. Но когда я удаляю сообщение по идентификатору сообщения, запись по-прежнему существует в пользовательском сообщении, и мне нужно удалить сразу две эти таблицы.

Я использовал следующий запрос:

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

Затем я тестирую

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

Но эти два запроса не решают эту задачу.

Ответы:


137

Разве нельзя просто разделить их точкой с запятой?

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

ИЛИ ЖЕ

Просто используйте, INNER JOINкак показано ниже

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

1
что произойдет, если я захочу поместить этот код в цикл? Я знаю, что могу поставить точку с запятой абсолютно.
mehdi

1
Его можно завернуть в петлю. Вы можете сделать это программно и отправить идентификатор сообщения в качестве параметра. Пока вы не отправляете ему один и тот же идентификатор, он не будет выполнять удаление снова и снова.
Эрик

4
Если вы сделаете это в двух запросах, вам действительно следует заключить это в транзакцию. Что касается выполнения запросов на удаление в цикле, лучше сформулировать один запрос для выполнения всех удалений.
JohnFx

1
Оформить заказ еще один пример запроса на удаление с присоединениями bennadel.com/blog/…
Бабар

21
Не работает с SQL Server: неправильный синтаксис рядом с ','.
Пол-Себастьян Маноле

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

перевод: удалить из таблицы сообщения, где messageid = 1, если таблица uersmessages имеет messageid = messageid табличных сообщений , удалить эту строку таблицы uersmessages .


комментарий для всех: как показано в этом примере, важно указать, в какой таблице удаление должно работать. Отличный пост @angry_kiwi
Raphael_b

Мне нужно было просто изменить порядок, FROM сообщения пользователя b сообщения LEFT JOIN a
Пабло

15

Вы должны либо создать с FOREIGN KEYпомощью ON DELETE CASCADE:

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

, или сделать это с помощью двух запросов в транзакции:

START TRANSACTION;;

DELETE
FROM    usermessages
WHERE   messageid = 1

DELETE
FROM    messages
WHERE   messageid = 1;

COMMIT;

Однако транзакция влияет только на InnoDBтаблицы.


3
Вы можете удалить из нескольких таблиц одним запросом! dev.mysql.com/doc/refman/5.0/en/delete.html
txwikinger 05

Да, ты можешь! Но для меня ... легче сделать то, что сказал мой ответ.
Эрик

Я добавил каскад на аналогичную свою таблицу. Когда я попытался удалить только из одной таблицы, он удалил запись, а связанную оставил сиротой. Что хорошего в ограничении?
barfoon

@barfoon: это твой стол InnoDB?
Quassnoi

@Quassnoi Упс! Я определенно думал, что это было глупо. Все таблицы MyISAM. Могу ли я изменить их все на лету с данными в них? Или с этим есть проблемы?
barfoon

7

У вас есть два варианта:

Сначала выполните две инструкции внутри транзакции:

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

Или вы можете настроить ON DELETE CASCADE с внешним ключом. Это лучший подход.

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

Вы можете узнать больше о КАСКАДЕ УДАЛЕНИЯ здесь .


7

нет необходимости в 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 просто отсутствуют псевдонимы таблиц после удаления

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

3
Спасибо за Ваш ответ. Было бы более полезно, если бы вы попытались объяснить, почему это сработает и почему решение OPs не работает.
DdW

1

Попробуйте это пожалуйста

DELETE FROM messages,usersmessages

USING messages

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

WHERE messages.messsageid='1'

0

Попробуй это..

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

Приведу idкак образец колонки.

Рад, что это помогает. :)


Чтобы asterikses ( *) отображались правильно, вам нужно сделать отступ запроса 4 пробелами перед ним.
Ал.Г.

0

Вы также можете использовать это для удаления определенного значения, когда оба столбца имеют 2 или несколько одинаковых имен столбцов.

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

есть другой способ, который здесь не упоминается (я еще не полностью тестировал его производительность), вы можете установить массив для всех таблиц -> строки, которые вы хотите удалить, как показано ниже

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

тогда вы можете перенаправить пользователя на домашнюю страницу.

header('LOCATION:' . $home_page);

надеюсь, это кому-то поможет :)

благодаря


Это может кому-то помочь ... похоже, PHP, хотя я не думаю, что это обязательно в рамках вопроса :)
Том Буш
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.