UPDATE — это команда «поменять данные в строках, которые уже есть». Не добавить новые (для этого INSERT), не удалить (DELETE), а именно поправить существующие.
Представь, что таблица — это блокнот с контактами. INSERT — это «добавить нового человека на чистую страницу». DELETE — «вырвать страницу с человеком, который тебе больше не нужен». А UPDATE — «зачеркнуть старый телефон Ани и написать сверху новый, потому что она поменяла номер».
Зачем нужен UPDATE
Данные в реальной жизни меняются постоянно:
- Пользователь сменил email — в строке у него надо обновить поле
email.
- Заказ оплатили — поле
status меняется с 'pending' на 'paid'.
- У товара выросла цена — поле
price нужно увеличить.
UPDATE — это инструмент именно для таких правок. Без него пришлось бы удалять строку и вставлять заново — а это и медленнее, и потеряются связи (например, на эту строку могли ссылаться другие таблицы по id).
Базовый синтаксис
UPDATE users
SET display_name = 'Аня (verified)'
WHERE id = 42;
По частям:
UPDATE users — какую таблицу правим.
SET display_name = 'Аня (verified)' — какое поле и на что меняем.
WHERE id = 42 — в какой строке (или строках).
Если перевести на русский: «В таблице users найди строку с id = 42 и поменяй у неё поле display_name на 'Аня (verified)'.» Всё.
Пример с таблицей
Есть таблица users:
Аня купила премиум, надо поменять её tier на 'gold':
UPDATE users
SET tier = 'gold'
WHERE id = 1;
После запроса таблица:
Всё остальное у Ани не тронули — только поле tier. Боба и Веру тоже не тронули — WHERE id = 1 их отсёк.
Несколько полей за один раз
SET принимает сколько угодно присваиваний через запятую:
UPDATE users
SET tier = 'gold',
upgraded_at = NOW(),
is_verified = TRUE
WHERE id = 1;
Все три поля поменяются в одной операции. Никаких промежуточных состояний — между апдейтами никто не увидит, что tier уже gold, а upgraded_at ещё пустой. Либо всё сразу, либо ничего (если что-то упадёт — откатится целиком).
WHERE — это не опция
Самая дорогая ошибка SQL — забыть WHERE:
UPDATE users SET tier = 'gold';
Никакого предупреждения. PostgreSQL и MySQL сделают как сказано — и таблица будет испорчена. На прод-базе в миллион строк такой запрос восстанавливается из бэкапа час, а нервы — несколько дней.
Защитные привычки, которые стоит выработать сразу:
1. Сначала SELECT, потом UPDATE с тем же WHERE:
SELECT id, name, tier FROM users WHERE id = 42;
UPDATE users SET tier = 'gold' WHERE id = 42;
2. Внутри транзакции — если ошибся, можно откатить:
BEGIN;
UPDATE users SET tier = 'gold' WHERE email = 'anya@example.com';
COMMIT;
UPDATE 1 означает «обновлена одна строка». Если ожидаешь одну, а Postgres говорит «247» — что-то пошло не так, лучше откатить и разобраться.
Условие посложнее
WHERE принимает любые условия — те же, что и в обычном SELECT:
UPDATE users
SET promo_code = 'WELCOME10'
WHERE country = 'Russia' AND tier = 'free';
UPDATE orders
SET status = 'archived'
WHERE created_at < NOW() - INTERVAL '1 year';
Можешь использовать AND/OR/NOT/IN/BETWEEN/LIKE — всё то же, что в обычной выборке.
SET со старым значением
В SET можно использовать текущее значение колонки для расчёта нового:
UPDATE products
SET price = price * 1.10;
UPDATE users
SET points = points + 5
WHERE id = 42;
Postgres сначала прочитает текущее значение, потом запишет новое — атомарно. Между этими двумя действиями никто не успеет вмешаться.
Частые ошибки новичков
1. UPDATE без WHERE. Уже разобрали. Привычка: набирать UPDATE table WHERE сразу, до заполнения SET — тогда забыть невозможно.
2. Опечатка в имени колонки. PostgreSQL поймает большинство — SET nmae = 'x' упадёт с «column does not exist». Но если опечатка совпадёт с другой реальной колонкой (tear вместо tier) — апдейт пройдёт молча и испортит данные. Помогают SELECT перед UPDATE и code review.
3. Кавычки в строках. Строки и даты — одинарные кавычки '...'. Двойные кавычки в PostgreSQL — это для имён колонок:
UPDATE users SET name = 'Аня' WHERE id = 1;
UPDATE users SET name = "Аня" WHERE id = 1;
4. Race condition при чтении-изменении-записи. Классика на счетах:
SELECT balance FROM accounts WHERE id = 1;
UPDATE accounts SET balance = 70 WHERE id = 1;
Между SELECT и UPDATE другая транзакция могла снять ещё 50 — баланс стал 50. А мы перетёрли его на 70. Минус 50 ушли в никуда.
Правильно — арифметика прямо в SET, без чтения в код:
UPDATE accounts SET balance = balance - 30 WHERE id = 1 AND balance >= 30;
Postgres всё посчитает в одной операции, никто не успеет вмешаться.
5. Перепутанный AND/OR. В сложных условиях ставь скобки явно:
UPDATE users
SET bonus = 100
WHERE (sex = 'M' AND country = 'Russia')
OR (sex = 'F' AND age > 25);
Без скобок Postgres разрулит по приоритету (AND сильнее OR), но угадывать — плохая привычка. Скобки — твой друг.
6. Касты типов. UPDATE users SET age = '30' — Postgres скастит строку в число. Но SET age = '' упадёт. На bulk-миграциях такие баги вылезают на одной-двух «грязных» строках где-нибудь посреди ночи.
Мини-резюме
UPDATE меняет данные в существующих строках. Структуру таблицы не трогает (для этого ALTER TABLE).
SET — какие поля и на что менять, через запятую можно сразу несколько.
WHERE обязателен. Без него обновятся все строки. Привычка: писать сразу UPDATE table WHERE, потом дописывать SET.
- Перед апдейтом на проде —
SELECT с тем же WHERE, посмотреть что попадёт.
- Всю арифметику делать в SQL (
balance = balance - 30), а не «прочитал → посчитал в коде → записал». Так не будет race condition.
UPDATE— это команда «поменять данные в строках, которые уже есть». Не добавить новые (для этогоINSERT), не удалить (DELETE), а именно поправить существующие.Представь, что таблица — это блокнот с контактами.
INSERT— это «добавить нового человека на чистую страницу».DELETE— «вырвать страницу с человеком, который тебе больше не нужен». АUPDATE— «зачеркнуть старый телефон Ани и написать сверху новый, потому что она поменяла номер».Зачем нужен UPDATE
Данные в реальной жизни меняются постоянно:
email.statusменяется с'pending'на'paid'.priceнужно увеличить.UPDATE— это инструмент именно для таких правок. Без него пришлось бы удалять строку и вставлять заново — а это и медленнее, и потеряются связи (например, на эту строку могли ссылаться другие таблицы поid).Базовый синтаксис
UPDATE users SET display_name = 'Аня (verified)' WHERE id = 42;По частям:
UPDATE users— какую таблицу правим.SET display_name = 'Аня (verified)'— какое поле и на что меняем.WHERE id = 42— в какой строке (или строках).Если перевести на русский: «В таблице
usersнайди строку сid = 42и поменяй у неё полеdisplay_nameна'Аня (verified)'.» Всё.Пример с таблицей
Есть таблица
users:Аня купила премиум, надо поменять её
tierна'gold':UPDATE users SET tier = 'gold' WHERE id = 1;После запроса таблица:
Всё остальное у Ани не тронули — только поле
tier. Боба и Веру тоже не тронули —WHERE id = 1их отсёк.Несколько полей за один раз
SETпринимает сколько угодно присваиваний через запятую:UPDATE users SET tier = 'gold', upgraded_at = NOW(), is_verified = TRUE WHERE id = 1;Все три поля поменяются в одной операции. Никаких промежуточных состояний — между апдейтами никто не увидит, что
tierужеgold, аupgraded_atещё пустой. Либо всё сразу, либо ничего (если что-то упадёт — откатится целиком).WHERE — это не опция
Самая дорогая ошибка SQL — забыть
WHERE:UPDATE users SET tier = 'gold'; -- → У ВСЕХ юзеров теперь gold. Включая тех, кто никогда не платил.Никакого предупреждения. PostgreSQL и MySQL сделают как сказано — и таблица будет испорчена. На прод-базе в миллион строк такой запрос восстанавливается из бэкапа час, а нервы — несколько дней.
Защитные привычки, которые стоит выработать сразу:
1. Сначала
SELECT, потомUPDATEс тем жеWHERE:-- Сначала проверили, та ли это строка SELECT id, name, tier FROM users WHERE id = 42; -- Если вернулось то, что ожидал — апдейтим UPDATE users SET tier = 'gold' WHERE id = 42;2. Внутри транзакции — если ошибся, можно откатить:
BEGIN; UPDATE users SET tier = 'gold' WHERE email = 'anya@example.com'; -- Postgres покажет «UPDATE 1» — норм. Если вдруг «UPDATE 247» — стоп. COMMIT; -- или ROLLBACK; если что-то не такUPDATE 1означает «обновлена одна строка». Если ожидаешь одну, а Postgres говорит «247» — что-то пошло не так, лучше откатить и разобраться.Условие посложнее
WHEREпринимает любые условия — те же, что и в обычномSELECT:-- Всем юзерам из России с tier = 'free' дать промокод UPDATE users SET promo_code = 'WELCOME10' WHERE country = 'Russia' AND tier = 'free'; -- Всем заказам старше года поменять статус на 'archived' UPDATE orders SET status = 'archived' WHERE created_at < NOW() - INTERVAL '1 year';Можешь использовать
AND/OR/NOT/IN/BETWEEN/LIKE— всё то же, что в обычной выборке.SET со старым значением
В
SETможно использовать текущее значение колонки для расчёта нового:-- Поднять цену всех товаров на 10% UPDATE products SET price = price * 1.10; -- Прибавить пользователю 5 баллов UPDATE users SET points = points + 5 WHERE id = 42;Postgres сначала прочитает текущее значение, потом запишет новое — атомарно. Между этими двумя действиями никто не успеет вмешаться.
Частые ошибки новичков
1. UPDATE без WHERE. Уже разобрали. Привычка: набирать
UPDATE table WHEREсразу, до заполненияSET— тогда забыть невозможно.2. Опечатка в имени колонки. PostgreSQL поймает большинство —
SET nmae = 'x'упадёт с «column does not exist». Но если опечатка совпадёт с другой реальной колонкой (tearвместоtier) — апдейт пройдёт молча и испортит данные. ПомогаютSELECTпередUPDATEи code review.3. Кавычки в строках. Строки и даты — одинарные кавычки
'...'. Двойные кавычки в PostgreSQL — это для имён колонок:-- Правильно UPDATE users SET name = 'Аня' WHERE id = 1; -- Неправильно — Postgres решит, что Аня это имя колонки UPDATE users SET name = "Аня" WHERE id = 1;4. Race condition при чтении-изменении-записи. Классика на счетах:
-- В приложении: SELECT balance FROM accounts WHERE id = 1; -- получили 100 -- расчёт в коде: new_balance = 100 - 30 = 70 UPDATE accounts SET balance = 70 WHERE id = 1;Между
SELECTиUPDATEдругая транзакция могла снять ещё 50 — баланс стал 50. А мы перетёрли его на 70. Минус 50 ушли в никуда.Правильно — арифметика прямо в
SET, без чтения в код:UPDATE accounts SET balance = balance - 30 WHERE id = 1 AND balance >= 30;Postgres всё посчитает в одной операции, никто не успеет вмешаться.
5. Перепутанный AND/OR. В сложных условиях ставь скобки явно:
-- Хочется: «всем мужчинам из России И всем женщинам старше 25 — дать бонус» UPDATE users SET bonus = 100 WHERE (sex = 'M' AND country = 'Russia') OR (sex = 'F' AND age > 25);Без скобок Postgres разрулит по приоритету (
ANDсильнееOR), но угадывать — плохая привычка. Скобки — твой друг.6. Касты типов.
UPDATE users SET age = '30'— Postgres скастит строку в число. НоSET age = ''упадёт. На bulk-миграциях такие баги вылезают на одной-двух «грязных» строках где-нибудь посреди ночи.Мини-резюме
UPDATEменяет данные в существующих строках. Структуру таблицы не трогает (для этогоALTER TABLE).SET— какие поля и на что менять, через запятую можно сразу несколько.WHEREобязателен. Без него обновятся все строки. Привычка: писать сразуUPDATE table WHERE, потом дописыватьSET.SELECTс тем жеWHERE, посмотреть что попадёт.balance = balance - 30), а не «прочитал → посчитал в коде → записал». Так не будет race condition.