UPDATE: промяна на редове
Накратко: UPDATE … SET сменя стойностите на колоните в редовете, които WHERE избере, а без WHERE ги сменя във всички редове на таблицата.
Проблем
Поскъпване
Доставчикът на млечни продукти вдига цените с 10%. От днес и магазинът трябва да продава с 10% по-скъпо всичко в категория „Млечни“.
Продуктите са пет. Можеш да смениш цените на ръка, една по една. Но утре ще е категория с 200 продукта, а при ръчно преписване грешките са сигурни.
Идеята
UPDATE … SET … WHERE
UPDATE казва коя таблица, SET казва коя колона и каква да стане, а WHERE казва в кои редове:
price * 1.1 се смята за всеки ред поотделно, с неговата цена. Прясното мляко беше 1,60 € и стана 1,76 €. ROUND(…, 2) закръглява до цент, защото цената е в евро и центове. Над резултата се вижда колко реда е променила заявката: пет.
По-точно, за любопитните
Без ROUND на екрана също ще видиш 1,76. Но за компютъра 1,6 · 1,1 е 1,7600000000000002, защото дробните числа се пазят в двоичен вид и не винаги точно. Тогава търсенето на цена 1,76 не намира прясното мляко:
Затова закръгляй парите, когато ги записваш. В истинските магазини цените често се пазят в цели центове (176) или в колона с точен десетичен тип, какъвто PostgreSQL и MySQL имат (DECIMAL). SQLite няма такъв тип.
В SET може да има няколко колони, разделени със запетая. Пристигат 30 баници, а цената им става 2,60 €:
stock + 30 взима старата наличност и добавя 30. В израза отдясно на = колоните са със старите стойности на реда.
Пробвай
Изпратена поръчка
Поръчка 59 е платена и днес тръгна с куриер. Смени състоянието ѝ на shipped.
Решение
UPDATE orders SET status = 'shipped' WHERE id = 59;UPDATE orders SET status = 'shipped' WHERE id = 59. Проверката гледа всички платени и изпратени поръчки. Така ще се види, ако си сменил и друга поръчка.
Виж го
UPDATE без WHERE
Управителят иска промоция: чаят от мента да е за 0,99 €. Някой пише набързо и забравя WHERE:
Всички 25 продукта вече струват 0,99 €, дори комплектът ножове, който беше 39 €. Базата не пита „сигурен ли си?“. Без WHERE заявката е за всички редове.
Тук бутонът „Нова база“ оправя всичко. В истинска база такъв бутон няма. Остават резервните копия и транзакциите: с транзакция промяната може да се отмени, преди да е потвърдена. Тях ще ги видиш по-нататък в курса.
Идеята
Първо SELECT
Навикът, който пази от това: преди UPDATE пусни SELECT със същото WHERE. Виждаш точно кои редове ще се променят, а нищо не се променя.
Напитките поскъпват с 5%. Категорията се знае по име, а номерът ѝ го дава подзаявка:
Четири продукта, точно тези, които трябва. Сега SELECT … FROM става UPDATE … SET, а WHERE остава същото:
Тук ROUND вече се вижда: 0,90 · 1,05 е 0,945, а 14,90 · 1,05 е 15,645. Цената става 0,95 € и 15,65 €.
Подзаявката в WHERE работи и в UPDATE, точно както в SELECT.
Пробвай
Забравените поръчки
Има нови поръчки (new) отпреди 2026 г., които никой не е платил. Откажи ги: състоянието им става cancelled.
Решение
UPDATE orders SET status = 'cancelled'
WHERE status = 'new' AND ordered_at < '2026-01-01';UPDATE orders SET status = 'cancelled' WHERE status = 'new' AND ordered_at < '2026-01-01'. Две поръчки, 4 и 10. Ако първо пуснеш SELECT със същото WHERE, ще видиш точно тях.
Упражнение
Две задачи
1. Промоция за продуктите, от които има много: всеки продукт с наличност над 50 поевтинява с 20%, закръглено до цент. Подаръчната карта е без категория и не влиза в промоцията.
Промоцията (проверява се цялата таблица products):
Решение
UPDATE products
SET price = ROUND(price * 0.8, 2)
WHERE stock > 50 AND category_id IS NOT NULL;UPDATE products SET price = ROUND(price * 0.8, 2) WHERE stock > 50 AND category_id IS NOT NULL. Пет продукта: кифлата, ябълките, картофите, водата и гъбите за почистване. Кифлата става 0,64 €. Без второто условие подаръчната карта за 20 € щеше да се продава за 16 €.
2. Мария Иванова (maria.ivanova@example.com) плати наведнъж всичките си нови поръчки. Смени състоянието им на paid. Намери клиента по имейла, с подзаявка.
Новите поръчки на Мария стават платени:
Решение
UPDATE orders SET status = 'paid'
WHERE status = 'new'
AND customer_id = (SELECT id FROM customers WHERE email = 'maria.ivanova@example.com');UPDATE orders SET status = 'paid' WHERE status = 'new' AND customer_id = (SELECT id FROM customers WHERE email = 'maria.ivanova@example.com'). Поръчки 34 и 46. Имейлът е уникален, затова подзаявката връща точно един клиент.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: NULL: няма стойност · Сметки в заявката · Подзаявки · INSERT: нови редове
- Продължава в: DELETE: изтриване на редове · UPSERT: вмъкни или обнови · Изгледи · Нормализация
- Задачи по темата: Промяна на данните