Как сделать UPDATE с подзапросами в SQLite
В SQLite часто возникает задача обновить строки одной таблицы на основе данных из других таблиц. Для этого используются вложенные запросы (подзапросы) в конструкции UPDATE. Рассмотрим корректный синтаксис и практические примеры.
Синтаксис UPDATE с подзапросами в SQLite
Базовая команда выглядит так:
UPDATE main_table
SET column1 = value1
WHERE main_table.id IN (SELECT id FROM related_table WHERE condition);Вместо IN можно использовать EXISTS, если нужно проверить наличие связанных записей.
Пример: обновление заказов по статусу клиента
Допустим, есть таблицы orders и customers. Нужно установить скидку 10% для всех заказов клиентов из Москвы:
UPDATE orders
SET discount = 10
WHERE customer_id IN (
SELECT id FROM customers
WHERE city = 'Москва'
);Этот запрос обновит только те строки orders, для которых customer_id совпадает с результатом подзапроса.
Использование EXISTS для сложных условий
Если нужно обновить строки, удовлетворяющие нескольким условиям из разных таблиц, применяйте EXISTS:
UPDATE products
SET price = price * 1.1
WHERE EXISTS (
SELECT 1 FROM categories
WHERE categories.id = products.category_id
AND categories.name = 'Электроника'
);Здесь обновление происходит только для товаров, у которых категория - «Электроника».
Обновление с JOIN (только в SQLite 3.33+)
Начиная с версии SQLite 3.33.0 (2020-08-14) поддерживается синтаксис UPDATE ... FROM, аналогичный JOIN:
UPDATE orders
SET status = 'processed'
FROM customers
WHERE orders.customer_id = customers.id
AND customers.rating > 4;Это более читаемый способ для сложных связей, но требует актуальной версии SQLite.
Типичные ошибки и их решение
- Ошибка: подзапрос возвращает NULL - используйте
COALESCEили проверку наIS NOT NULL. - Ошибка: обновление всех строк - всегда проверяйте условие
WHEREперед выполнением. - Ошибка: слишком медленный запрос - добавьте индексы на столбцы, участвующие в подзапросе.
Заключение
Обновление строк в SQLite с помощью подзапросов - мощный инструмент для массовых изменений. Используйте IN или EXISTS в зависимости от логики, а для новых версий - UPDATE ... FROM. Всегда тестируйте запрос на копии данных.