SQLUPDATEDMLtutorial

Что такое UPDATE в SQL? Изменение строк для начинающих

UPDATE — это команда «поменять данные в существующих строках». Простыми словами: что меняем, как обязательно сужать WHERE, как поменять сразу несколько колонок. Таблицы before/after, типичные ловушки новичков, мини-резюме и три задачки на закрепление.

4 мин чтенияСправочникSQL · UPDATE · DML · tutorial

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:

id name email tier
1 Аня anya@example.com free
2 Боб bob@example.com free
3 Вера vera@example.com gold

Аня купила премиум, надо поменять её tier на 'gold':

UPDATE users
SET tier = 'gold'
WHERE id = 1;

После запроса таблица:

id name email tier
1 Аня anya@example.com gold
2 Боб bob@example.com free
3 Вера vera@example.com gold

Всё остальное у Ани не тронули — только поле 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, посмотреть что попадёт.
  • Всю арифметику делать в SQL (balance = balance - 30), а не «прочитал → посчитал в коде → записал». Так не будет race condition.

Закрепи на практике

Решай задачи в SQL-тренажёре с мгновенной проверкой и подсказками.

Открыть тренажёр