Видалити з двох таблиць в одному запиті


85

У мене є дві таблиці в MySQL

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

Тепер, якщо я хочу видалити з таблиці повідомлень, це нормально. Але коли я видаляю повідомлення за повідомленнямиid, запис все ще існує в повідомленні користувача, і мені доводиться видаляти з цих двох таблиць одночасно.

Я використав такий запит:

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
що трапиться, якщо я хочу помістити цей код у цикл? я знаю, що можу поставити крапку з комою абсолютно.
Мехді

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

Мені довелося просто змінити порядок, ВІД повідомлень користувачів b ЛИВО ПРИЄДНАЙТЕСЯ повідомлення
Пабло

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

так, ти можеш! Але мені ... простіше зробити те, що сказано у моїй відповіді.
Ерік

Я додав каскад на подібному моєму столі. Коли я намагався видалити лише з 1 таблиці, він видалив запис, а відповідний залишився сиротою. Яка користь від обмеження?
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

немає потреби в ПРИЄДНАННЯ:

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
Дякую за вашу відповідь. Було б більш корисно, якщо ви спробуєте пояснити, чому це могло б спрацювати, а чому рішення з ОП - ні.
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.