Klucz obcy (ang. foreign key, w skrócie FK) to kolumna (albo zestaw kolumn) w jednej tabeli, której wartości muszą odpowiadać kluczowi głównemu (primary key) lub kluczowi unikalnemu w innej tabeli. Krótko: to fizyczne połączenie między tabelami, które sprawia, że baza wie, że wiersz „zamówienie” naprawdę należy do istniejącego „klienta”, a nie do widmowego ID, którego nikt nigdy nie wpisał.
Klucz obcy realizuje tzw. spójność referencyjną (referential integrity). Kiedy go zdefiniujesz, silnik bazy danych zaczyna pilnować, żebyś nie wstawił do tabeli zależnej wartości, której nie ma w tabeli nadrzędnej. Próbujesz dodać zamówienie z customer_id = 999, a takiego klienta nie ma? Baza odrzuci insert i rzuci błędem. To samo działa przy kasowaniu: nie usuniesz klienta, do którego wiszą zamówienia, chyba że jawnie ustawisz, co ma się wtedy stać.
Jak to wygląda w praktyce
Załóżmy klasyczny układ w PostgreSQL: tabela customers i tabela orders. Relację tworzysz tak:
CREATE TABLE orders (id SERIAL PRIMARY KEY, customer_id INT REFERENCES customers(id) ON DELETE CASCADE, total NUMERIC);
Tutaj customer_id to klucz obcy wskazujący na customers(id). Dorzuciłeś jeszcze ON DELETE CASCADE — to znaczy „jeśli skasuję klienta, posprzątaj też jego zamówienia”. Masz do wyboru kilka zachowań: CASCADE (kasuj w dół), SET NULL (zostaw sierotę z pustym wskazaniem), RESTRICT / NO ACTION (zablokuj kasowanie, jeśli coś wisi). Dobór zależy od tego, czy dane potomne mają sens bez rodzica.
Na co uważać
- Indeks na FK. Wiele baz (np. MySQL/InnoDB) tworzy indeks automatycznie, ale PostgreSQL już nie. Bez indeksu na kolumnie klucza obcego JOIN-y i kasowanie potrafią zamulić bazę przy większym ruchu.
- Typy muszą się zgadzać.
INTnie zlinkuje się zBIGINTani zVARCHAR. Klasyczny błąd debiutanta i „dlaczego mi nie tworzy constrainta”. - MyISAM ignoruje FK. W MySQL składnia przejdzie, ale silnik MyISAM po cichu nie egzekwuje reguły. Używaj InnoDB.
- NULL jest dozwolony — wiersz bez relacji (np. zamówienie bez przypisanego kuriera) jest OK, o ile kolumna nie ma
NOT NULL.
Mit do obalenia: klucz obcy nie spowalnia bazy „z definicji”. Spowalnia ją brak indeksu i nieprzemyślane kaskady, a nie sam constraint.
Pojęcia powiązane: klucz główny (primary key), klucz unikalny (unique key), relacja jeden-do-wielu, normalizacja, JOIN, spójność referencyjna, ograniczenia (constraints).