W aplikacji pojawia się nowe pole, ale tabela w bazie go nie ma. Polecenie ALTER TABLE zwykle pozwala zmienić jej strukturę bez tworzenia tabeli od nowa, choć składnia i wpływ operacji na działający system zależą od silnika bazy.

Zmiana tabeli wymaga dopasowania składni i oceny ryzyka
- Dodanie kolumny: użyj
ADD COLUMN, ale sprawdź składnię konkretnego silnika. - Usunięcie danych:
DROP COLUMNusuwa kolumnę z perspektywy zapytań, a zależności mogą wymagać osobnej decyzji. - Duża tabela: zmiana typu lub dodanie ograniczenia może wymagać skanowania albo przebudowy danych.
- Produkcja: przetestuj migrację na kopii danych i zaplanuj sposób wycofania zmiany.
ALTER TABLE zmienia schemat, a nie zawartość tabeli
Gdy nowa funkcja potrzebuje kolumny, zmieniasz strukturę istniejącej tabeli, a nie pojedyncze wartości w jej wierszach. Do modyfikacji danych służy zwykle UPDATE; ALTER TABLE dodaje, usuwa lub przekształca elementy schematu.
Podstawowy wzorzec wygląda tak:
ALTER TABLE nazwa_tabeli
ADD COLUMN nazwa_kolumny typ_danych;Przykładowo, w systemie zapisującym zamówienia można dodać pole na kod waluty:
ALTER TABLE orders
ADD COLUMN currency_code VARCHAR(3);Nowa kolumna bez wartości domyślnej nie uzupełnia automatycznie sensownych danych biznesowych. W wielu silnikach istniejące rekordy otrzymują NULL, więc zanim dodasz ograniczenie NOT NULL, sprawdź, co stanie się ze starszymi wierszami.
Składnia różni się między PostgreSQL, MySQL i SQL Server
Podobieństwo składni bywa zdradliwe: dodawanie kolumn wygląda niemal identycznie, ale zmiana typu lub nazwy już niekoniecznie. Nie kopiuj polecenia między silnikami bez sprawdzenia dokumentacji, szczególnie gdy skrypt ma działać na kilku środowiskach.
| Silnik | Dodanie kolumny | Zmiana typu |
|---|---|---|
| PostgreSQL | ADD COLUMN email text |
ALTER COLUMN email TYPE text |
| MySQL | ADD COLUMN email VARCHAR(255) |
MODIFY COLUMN email VARCHAR(255) |
| SQL Server | ADD email NVARCHAR(255) |
ALTER COLUMN email NVARCHAR(255) |
Różnice nie kończą się na słowie MODIFY czy ALTER. W SQL Server dodanie kolumny może obejmować ograniczenie DEFAULT, a opcja WITH VALUES wpływa na wartości zapisane w istniejących rekordach. Z kolei dokumentacja SQLite opisuje ograniczony zestaw bezpośrednio obsługiwanych zmian, więc część modyfikacji może wymagać innego podejścia.
Przy zmianie typu dane muszą dać się przekonwertować. W PostgreSQL można wskazać sposób konwersji przez USING, gdy automatyczne rzutowanie nie wystarczy; przed uruchomieniem sprawdź próbkę danych, bo wartości tekstowe nie zawsze pasują do nowego typu. Szczegóły składni opisuje dokumentacja PostgreSQL.
Dodanie kolumny może być szybkie, ale zmiana typu już kosztowna
Jedna linijka SQL potrafi uruchomić długą pracę na dysku. PostgreSQL wskazuje, że kolumna z niezmiennym, stałym domyślnym wyrażeniem może zostać dodana bez przepisywania wszystkich wierszy, natomiast domyślna wartość zmienna lub zmiana typu może wymagać przebudowy tabeli.
W MySQL 8.4 operacje ALTER TABLE mogą korzystać z algorytmów INSTANT, INPLACE albo COPY. Pierwszy zmienia metadane bez modyfikowania danych tabeli, drugi może przebudować ją w miejscu, a trzeci kopiuje wiersze; dostępność zależy od konkretnej operacji i rodzaju tabeli. Dokumentacja MySQL pokazuje, dlaczego samo „dodaję jedną kolumnę” nie wystarcza do oszacowania czasu i blokad.
Praktyczna reguła: jeśli operacja może zmienić lub zweryfikować istniejące wiersze, potraktuj ją jako potencjalnie kosztowną. W PostgreSQL polecenie dodające kilka zmian w jednym przebiegu przejmuje najbardziej restrykcyjną blokadę wymaganą przez dowolną z nich, dlatego łączenie zmian nie zawsze skraca niedostępność.
Najpierw rozwiąż problem istniejących rekordów
Załóżmy, że tabela orders zawiera miliony zamówień, a aplikacja ma zacząć zapisywać currency_code jako pole wymagane. Bezpieczniejszy plan zwykle rozdziela wdrożenie na etapy: najpierw dodajesz kolumnę dopuszczającą NULL, potem wdrażasz aplikację zapisującą walutę, uzupełniasz starsze rekordy i dopiero na końcu wymuszasz NOT NULL.
Taki podział ogranicza ryzyko, że nowa wersja aplikacji i stary schemat będą przez chwilę niezgodne. Uważam, że w systemie produkcyjnym mała, odwracalna migracja jest rozsądniejsza od jednego dużego skryptu, nawet gdy ten drugi wygląda krócej.
| Sytuacja | Możliwa przyczyna lub skutek | Co zrobić |
|---|---|---|
| Dodawana kolumna ma być obowiązkowa | Starsze rekordy mogą nie mieć wartości | Dodaj kolumnę jako dopuszczającą NULL, uzupełnij dane, potem dodaj ograniczenie. |
| Zmiana typu kończy się błędem | Wartości nie dają się przekonwertować automatycznie | Znajdź niezgodne rekordy i określ regułę konwersji przed migracją. |
| Operacja długo czeka lub blokuje zapisy | Silnik potrzebuje blokady albo przebudowuje dane | Sprawdź wymagany algorytm, blokady i rozmiar tabeli; testuj na kopii zbliżonej do produkcji. |
| Usuwana kolumna jest używana przez aplikację | Zapytania, widoki lub inne zależności nadal się do niej odwołują | Najpierw przestań jej używać w kodzie, a dopiero potem usuń ją ze schematu. |
Przed wdrożeniem sprawdź blokady i plan odwrotu
Przed uruchomieniem migracji ustal, czy operacja przebuduje tabelę, jak długo może trwać i czy w tym czasie aplikacja będzie mogła czytać oraz zapisywać dane. W MySQL można wymagać określonego algorytmu, aby polecenie zakończyło się błędem zamiast nieoczekiwanie przejść do kosztownego kopiowania, o ile dana zmiana obsługuje taką opcję.
Przed zmianą przygotuj kopię zapasową, przetestuj skrypt na danych o podobnej skali i sprawdź zależności: indeksy, klucze obce, widoki oraz kod aplikacji. Sama kopia nie rozwiązuje problemu wycofania migracji, jeśli po zmianie aplikacja zdąży zapisać wartości w nowym formacie. Plan odwrotu powinien uwzględniać również te nowe dane.
Najbezpieczniejsza zmiana zaczyna się od pytania o dane
Przed każdym ALTER TABLE odpowiedz sobie na trzy pytania: co stanie się ze starymi rekordami, jakiego algorytmu i blokady użyje silnik oraz czy aplikacja poradzi sobie z przejściowym stanem schematu. Jeśli odpowiedź na którekolwiek z nich jest niejasna, rozbij migrację na etapy. Tabela zmieni wtedy kształt bez niespodzianki w środku wdrożenia.
