Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як оновити чи видалити рядки за умовою з іншої таблиці в MySQL?

MySQL підтримує багатотабличні UPDATE і DELETE з JOIN:

-- позначити замовлення заблокованих користувачів
UPDATE orders o
JOIN users u ON u.id = o.user_id
SET o.status = 'cancelled'
WHERE u.is_banned = 1 AND o.status = 'pending';

-- видалити товари з кошиків, яких більше немає в продажу
DELETE ci
FROM cart_items ci
JOIN products p ON p.id = ci.product_id
WHERE p.is_active = 0;

У DELETE перед FROM вказують, з якої таблиці видаляти (DELETE ci), - інакше можна видалити з обох.

Синтаксис відрізняється між СУБД:

-- PostgreSQL
UPDATE orders o SET status = 'cancelled'
FROM users u
WHERE u.id = o.user_id AND u.is_banned;

DELETE FROM cart_items ci USING products p
WHERE p.id = ci.product_id AND NOT p.is_active;

Переносимий варіант - підзапит: WHERE user_id IN (SELECT id FROM users WHERE is_banned = 1).

Обмеження MySQL: не можна змінювати таблицю й одночасно читати з неї в підзапиті:

DELETE FROM orders WHERE id IN (SELECT id FROM orders WHERE ...);
-- ERROR 1093: You can't specify target table 'orders' for update in FROM clause

Обхід - обгорнути підзапит у ще одну похідну таблицю (MySQL матеріалізує її) або переписати через JOIN.

Обережно з масовими змінами:

  • Спершу виконати той самий запит як SELECT і перевірити кількість рядків.
  • Великі оновлення - порціями з LIMIT (у багатотабличних UPDATE/DELETE LIMIT не дозволений - порції роблять за діапазонами id).
  • Блокування: UPDATE ... JOIN блокує рядки, які читає, і в об'єднаній таблиці теж - під навантаженням можливі очікування й deadlock'и.

У Laravel: DB::table('orders')->join('users', ...)->where(...)->update([...]) генерує багатотабличний UPDATE для MySQL.

Докладніше в документації: UPDATE

1

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання