UPDATE меняет уже существующие строки
INSERT добавляет новые строки. UPDATE правит те, что уже лежат в таблице. Конструкция короткая, и её стоит запомнить:
UPDATE table_name
SET column = value
WHERE condition;
Рабочий пример:
SET описывает, что менять. WHERE — какие строки трогать. Всё остальное в таблице остаётся как было.
Почему WHERE в UPDATE — это не «по желанию»
Формально WHERE действительно необязателен. Но на практике именно его пропуск превращает обычный вечер джуна в катастрофу:
UPDATE users SET status = 'inactive';
-- теперь все пользователи без исключения неактивны
Если фильтра нет, под условие попадает каждая строка — и SQLite молча это сделает. Возьмите за правило сначала писать WHERE, и только потом SET. Одна эта привычка спасает от кучи неприятных сюрпризов.
Если сомневаетесь, что WHERE написан правильно, прогоните то же условие через SELECT:
Одно и то же условие, два запроса. SELECT — это, по сути, ваш тестовый прогон.
Обновление нескольких столбцов sqlite
Перечисляйте присваивания через запятую внутри одного SET. Один SET — сколько угодно столбцов:
Один поход в базу, одна строка, три обновлённых столбца. Не пишите три отдельных UPDATE, если хватит одного.
Выражения в правой части =
После = не обязательно ставить литерал. Туда подойдёт любое выражение — в том числе и такое, которое ссылается на текущее значение самой колонки:
price * 1.10 берёт текущую цену, умножает её и записывает результат обратно. Правую часть SQLite вычисляет по тем значениям, которые есть в строке до того, как сработают присваивания этого UPDATE, поэтому в выражении можно спокойно ссылаться сразу на несколько столбцов:
UPDATE products SET price = price * 1.10, stock = stock + price;
-- 'price' в правой части здесь — это СТАРАЯ цена, а не только что обновлённая.
UPDATE ... FROM: подтягиваем значения из другой таблицы
Начиная с версии SQLite 3.33, в UPDATE появилась поддержка конструкции FROM — это даёт возможность обновлять данные одной таблицы на основе другой. На сегодня это самый аккуратный способ синхронизировать данные между таблицами:
Подзапрос считает суммы по каждому клиенту, а внешний UPDATE подтягивает эти результаты обратно в таблицу customers по полю id. Без конструкции UPDATE ... FROM пришлось бы писать коррелированный подзапрос для каждого столбца — выглядело бы куда грязнее.
Несколько важных моментов:
- Целевая таблица указывается после
UPDATE, а не в спискеFROM. - Соединение задаётся через
WHERE— ключевого словаONздесь нет. - Если соединение может дать несколько совпадений в
FROM, результат непредсказуем. Следите за тем, чтобы ключи соединения давали не больше одного совпадения на строку.
RETURNING: смотрим, что именно изменилось
Начиная с версии 3.35, SQLite позволяет команде UPDATE сразу возвращать изменённые строки. Удобно, когда приложению нужны новые значения без дополнительного SELECT:
Вы получаете обратно те самые строки, которых коснулось обновление, уже с новыми значениями. Это экономит лишний поход в базу и убирает целый класс гонок в конкурентном коде. Чуть дальше в этой главе есть отдельная страница про RETURNING.
UPDATE OR REPLACE: что делать при конфликте ограничений
Если ваш UPDATE нарушит ограничение UNIQUE, по умолчанию SQLite просто прервёт выполнение с ошибкой. Через клаузу OR можно задать другую стратегию:
Доступные варианты: OR ABORT (по умолчанию), OR REPLACE, OR IGNORE, OR FAIL и OR ROLLBACK. Опасный из них — REPLACE: он удаляет конфликтующую строку, и это может каскадно прокатиться по внешним ключам. Используйте его только тогда, когда действительно имеете в виду «если строка с таким уникальным значением уже есть — выбрось её».
Для типичных задач в стиле upsert обычно понятнее отдельный синтаксис INSERT ... ON CONFLICT — про него есть отдельная страница.
Оборачивайте рискованный UPDATE в транзакцию
Когда вы меняете много строк или запускаете несколько команд UPDATE, которые должны отработать как единое целое, оборачивайте их в транзакцию. Если что-то пойдёт не так — откатитесь к исходному состоянию:
Если второй запрос упадёт (например, сработает ограничение), ROLLBACK откатит и первый. Без транзакции остался бы недоделанный перевод: у Ады списано 25, у Бориса по-прежнему ноль. Транзакциям посвящена отдельная глава дальше — пока просто запомните, что они есть и что массовые обновления почти всегда стоит оборачивать в транзакцию.
Типичные ошибки
Короткий список граблей, на которые наступают чаще всего:
- Забыли
WHERE— обновятся все строки до единой. Прочитайте запрос вслух, прежде чем выполнять. - Не тот оператор в
WHERE—WHERE status = NULLне вернёт ни одной строки. НуженIS NULL. Подробнее — в разделе про операторы. - Подзапрос возвращает несколько строк там, где вы ждёте одну. Используйте
LIMIT 1или агрегируйте результат, иначе получите либо ошибку, либо неожиданные данные. - Путают
UPDATE OR REPLACEи UPSERT.OR REPLACEудаляет конфликтующие строки.INSERT ... ON CONFLICT DO UPDATEменяет их на месте. Это разные операции.
Дальше: DELETE
UPDATE меняет строки, DELETE их удаляет. Дисциплина с WHERE та же самая — и привычка «сначала прогнать SELECT» точно так же спасёт вас от тех же бед. Об этом — на следующей странице.
Часто задаваемые вопросы
Какой базовый синтаксис UPDATE в SQLite?
UPDATE table_name SET column = value WHERE condition;. В SET перечисляются столбцы и их новые значения, а WHERE определяет, какие строки обновятся. Если забыть WHERE, обновится вся таблица — без шуток.
Как обновить несколько столбцов одним запросом?
Перечислите присваивания через запятую внутри одного SET: UPDATE users SET name = 'Ada', email = 'ada@x.com' WHERE id = 1;. Один запрос — одно обращение к БД — одна обновлённая строка. Повторять SET для каждого столбца не нужно.
Можно ли в SQLite обновить таблицу данными из другой таблицы?
Да, для этого есть UPDATE ... FROM (появилось в SQLite 3.33). Синтаксис: UPDATE target SET col = source.col FROM source WHERE target.id = source.id;. Это самый чистый способ перенести значения между таблицами без подзапросов в SET.