W tabeli klientów trzeba poprawić adres jednej osoby, ale warunek po nazwisku może pasować do kilku rekordów. Instrukcja UPDATE zmieni wskazane kolumny w pasujących wierszach, choć o tym, które wiersze zostaną objęte zmianą, decyduje precyzja warunku.

Zakres zmiany wynika z warunku, a jej kontrola z użytego silnika
WHEREokreśla, które rekordy zmienisz; bez niego aktualizacja obejmie całą tabelę.SETmoże przypisać stałą wartość albo obliczyć ją na podstawie aktualnych danych.- Podgląd przez
SELECTpomaga sprawdzić warunek przed zapisem. - Transakcja daje możliwość wycofania zmian przed zatwierdzeniem, jeśli silnik i ustawienia na to pozwalają.
Najpierw zawęź rekordy, potem ustaw nowe wartości
Najgroźniejszy fragment zapytania często mieści się w jednym pominiętym słowie. Gdy zabraknie WHERE, baza zaktualizuje wszystkie wiersze tabeli, dlatego warunek dobrze jest napisać i sprawdzić przed uruchomieniem zmiany.
UPDATE Klienci
SET Miasto = 'Gdańsk'
WHERE IdKlienta = 1842;
W tym przykładzie SET wskazuje kolumnę do zmiany, a WHERE wybiera rekord po identyfikatorze. Jeśli klient ma unikalny klucz główny, taki warunek jest bezpieczniejszy niż filtrowanie po nazwisku, które może się powtarzać.
Przy aktualizacji kilku kolumn rozdziel przypisania przecinkami. Nie stawiaj przecinka przed WHERE:
UPDATE Klienci
SET Miasto = 'Gdańsk',
KodPocztowy = '80-001'
WHERE IdKlienta = 1842;
Przed wykonaniem zmiany możesz uruchomić zapytanie SELECT z tym samym warunkiem. Uważam, że to najprostszy sposób, by wykryć pomyłkę w filtrze, zanim dotknie danych.
Wyrażenie w SET pozwala przeliczyć wartość dla każdego wiersza
Cena może zależeć od obecnej ceny, stan magazynowy od poprzedniego stanu, a status od kilku pól naraz. W takich przypadkach po prawej stronie przypisania umieść wyrażenie:
UPDATE Produkty
SET Cena = Cena * 0.95
WHERE Kategoria = 'Ksiazki';
To obniża cenę produktów z pasującej kategorii o pięć procent. Jeśli nowe wartości mają zależeć od kategorii lub progu, użyj CASE, który wybiera wynik na podstawie warunku:
UPDATE Produkty
SET Cena = CASE
WHEN Kategoria = 'Ksiazki' THEN Cena * 0.95
WHEN Kategoria = 'Akcesoria' THEN Cena * 0.90
ELSE Cena
END
WHERE Aktywny = 1;
Warunek w CASE wybiera nową wartość, a zewnętrzne WHERE ogranicza grupę rekordów, które w ogóle zostaną zmienione. To rozróżnienie przydaje się szczególnie wtedy, gdy część produktów ma zachować dotychczasową cenę.
Przy aktualizacji z drugiej tabeli pilnuj jednego dopasowania
Gdy nowa cena albo status pochodzi z tabeli importowej, zapytanie musi połączyć rekord źródłowy z docelowym. Najpierw sprawdź, czy klucz łączenia daje najwyżej jeden pasujący wiersz źródła na jeden aktualizowany rekord; duplikaty mogą sprawić, że wybór danych do zmiany będzie niejednoznaczny.
Składnia zależy od bazy. W PostgreSQL oraz SQL Server można użyć FROM, a w MySQL zapis wielotabelowy umieszcza tabele po UPDATE:
-- PostgreSQL
UPDATE Produkty AS p
SET Cena = i.NowaCena
FROM ImportCen AS i
WHERE p.Kod = i.Kod;
-- SQL Server
UPDATE p
SET Cena = i.NowaCena
FROM Produkty AS p
JOIN ImportCen AS i ON p.Kod = i.Kod;
-- MySQL
UPDATE Produkty AS p
JOIN ImportCen AS i ON p.Kod = i.Kod
SET p.Cena = i.NowaCena;
Dokumentacja PostgreSQL 17 ostrzega, że przy UPDATE ... FROM tabela źródłowa powinna dostarczać najwyżej jeden wiersz dla każdego rekordu docelowego. W przeciwnym razie wybór źródłowego wiersza może być nieprzewidywalny. Przed aktualizacją uruchom więc zapytanie kontrolne grupujące import po kluczu i wyszukaj klucze występujące więcej niż raz.
Transakcja pomaga wycofać zmianę, zanim ją zatwierdzisz
Załóżmy, że import zawiera 240 aktywnych produktów, ale aktualizacja miała objąć tylko 24 rekordy z jednego działu. Zamiast od razu zatwierdzać zmianę, sprawdź liczbę rekordów z tym samym warunkiem, wykonaj aktualizację w transakcji i porównaj wynik z oczekiwanym zakresem.
BEGIN;
SELECT COUNT(*)
FROM Produkty
WHERE Kategoria = 'Ksiazki'
AND Aktywny = 1;
UPDATE Produkty
SET Cena = Cena * 0.95
WHERE Kategoria = 'Ksiazki'
AND Aktywny = 1;
-- Po kontroli:
COMMIT;
-- Jeśli zakres lub wynik się nie zgadza:
-- ROLLBACK;
BEGIN, COMMIT i ROLLBACK to typowe polecenia transakcyjne, lecz ich obsługa zależy od silnika, klienta i ustawień połączenia. Po zatwierdzeniu transakcji samo ROLLBACK nie cofnie już tych zmian.
| Sytuacja | Możliwa przyczyna lub skutek | Co zrobić |
|---|---|---|
| Zapytanie zmienia więcej wierszy, niż zakładano | Warunek jest zbyt szeroki albo dopasowanie obejmuje powtarzające się wartości. | Przerwij transakcję przez ROLLBACK, a potem sprawdź warunek w SELECT. |
| Zapytanie nie zmienia żadnego wiersza | Filtr nie pasuje do danych albo wartość została już zmieniona. | Sprawdź wartości użyte w filtrze i to, czy dane nie różnią się formatem. |
| Aktualizacja z importu wybiera niejednoznaczne dane | Klucz źródłowy występuje w tabeli importowej więcej niż raz. | Usuń lub rozstrzygnij duplikaty przed zmianą tabeli docelowej. |
| Wynik po zatwierdzeniu jest błędny | Transakcja została już zatwierdzona lub nie obejmowała zmiany. | Odtwórz prawidłowe wartości z kopii albo dziennika zmian; sam ROLLBACK nie wystarczy. |
Jeśli aktualizacja działa w aplikacji produkcyjnej, kontrolę liczby zmienionych wierszy dodaj także do kodu, który wykonuje zapytanie. Jednorazowy podgląd nie ochroni kolejnego uruchomienia skryptu z innymi parametrami.
PostgreSQL, SQL Server i MySQL różnią się raportowaniem zmian
Po wykonaniu polecenia przydaje się wiedzieć, które rekordy rzeczywiście się zmieniły. PostgreSQL obsługuje RETURNING, SQL Server ma klauzulę OUTPUT, a składnia UPDATE w MySQL 8.4 nie zawiera odpowiednika żadnej z tych klauzul.
-- PostgreSQL
UPDATE Produkty
SET Cena = Cena * 0.95
WHERE Kod = 'A-17'
RETURNING Kod, Cena;
-- SQL Server
UPDATE Produkty
SET Cena = Cena * 0.95
OUTPUT deleted.Cena AS StaraCena,
inserted.Cena AS NowaCena
WHERE Kod = 'A-17';
PostgreSQL zwraca nowe wartości z RETURNING. SQL Server pozwala w OUTPUT zestawić wartość sprzed zmiany z nową, co ułatwia kontrolę lub zapis audytowy. W MySQL liczbę zmienionych rekordów można odczytać z informacji zwróconej przez sterownik, ale jej interpretacja zależy od tego, czy klient raportuje rekordy zmienione, czy dopasowane.
Różnica jest praktyczna: jeśli potrzebujesz zestawienia „przed i po” w jednym poleceniu, SQL Server udostępnia je wprost, a PostgreSQL zwraca stan po aktualizacji. Wybierając wariant dla MySQL, uwzględnij ustawienia sterownika i nie traktuj samej liczby jako dowodu, że zmieniły się dokładnie te rekordy, które planowano.
Dobra aktualizacja kończy się kontrolą wyniku
Przed uruchomieniem ustal, które wiersze spełniają warunek, a po zmianie sprawdź zakres i nowe wartości. Gdy zapytanie korzysta z drugiej tabeli, skontroluj unikalność dopasowania, a w pracy na ważnych danych trzymaj zmianę w transakcji do czasu weryfikacji.
Sam zapis UPDATE ... SET ... WHERE ... jest krótki. Bezpieczne wykonanie zależy od tego, czy warunek naprawdę wskazuje właściwe rekordy i czy potrafisz ocenić rezultat przed zatwierdzeniem.
