Bazy danych i SQL w kwalifikacji INF.03: najważniejsze zasady, przykłady i powiązane pytania w banku. Skrót działu, który otwiera lekcje o projektowaniu baz danych.
Projektowanie bazy wraca w każdej sesji: w części pisemnej jako pytania o klucze i relacje, w praktycznej przy tworzeniu tabel, łączeniu danych i wyświetlaniu wyniku w aplikacji. Warto rozumieć, skąd bierze się rezultat zapytania, zamiast uczyć się samych nazw poleceń. Ten artykuł to skrót; pełne omówienie jest w pięciu lekcjach wymienionych na końcu.
Od modelu danych do tabel
Klucz główny jednoznacznie wskazuje wiersz, a klucz obcy łączy go z rekordem w innej tabeli. Jeden klient może mieć wiele zamówień, więc to relacja jeden do wielu: klucz obcy klient_id stoi po stronie zamówień i wskazuje na klient.id.
Tabela klient z kluczem głównym id i tabela zamowienie z kluczem obcym klient_id, który wskazuje na klient.id; zamówienie 13 ma NULL, bo powstało bez klienta
Relacji wiele do wielu nie da się zapisać dwiema tabelami, bo obie strony mają wiele powiązań. Wchodzi wtedy tabela pośrednia z dwoma kluczami obcymi, które razem tworzą klucz główny:
Tabele uczen i grupa połączone tabelą uczen_grupa: dwa klucze obce, razem klucz główny, jeden wiersz na każdą parę uczeń i grupa
Ograniczenie
Co pilnuje
PRIMARY KEY
jednoznaczność wiersza
FOREIGN KEY
spójność powiązań między tabelami
UNIQUE
brak powtórzeń w kolumnie
NOT NULL
wartość musi istnieć
Normalizacja bez definicji na pamięć
1.
Pierwsza postać normalna: pojedyncza wartość w każdym polu, a nie lista telefonów w jednej komórce.
2.
Druga: bez zależności od części klucza złożonego.
3.
Trzecia: bez zależności pośrednich, na przykład nazwy miasta zależnej od kodu pocztowego zamiast od identyfikatora klienta.
Celem jest ograniczenie powtórzeń i błędów przy zmianach: gdy nazwa kategorii występuje w każdym produkcie, literówkę poprawia się w wielu miejscach. Po wydzieleniu tabeli kategoria nazwa jest zapisana raz, a produkt trzyma tylko klucz obcy.
SELECT, GROUP BY i HAVING
1
2
3
4
SELECTklient_id,COUNT(*)ASile
FROMzamowienie
GROUPBYklient_id
HAVINGCOUNT(*)>=3;
WHERE filtruje wiersze przed grupowaniem, HAVING filtruje gotowe grupy, ORDER BY ustala kolejność, a LIMIT ogranicza liczbę rekordów.
Złączenia i wiersze bez pary
Złączenie
Co zwraca
INNER JOIN
tylko pasujące rekordy z obu tabel
LEFT JOIN
każdy wiersz z lewej tabeli, braki po prawej jako NULL
Z tej różnicy bierze się gotowy wzorzec na pytanie „kto nic nie zamówił":
Samo LEFT JOIN pokaże WSZYSTKICH klientów, także tych z zamówieniami; dopiero warunek na NULL zostawia klientów bez pary.
NULL, czyli brak znanej wartości
NULL nie jest zerem ani pustym tekstem, więc zwykłe porównanie z nim nie działa:
1
2
3
4
5
6
WHEREkwota=NULL-- ZERO wierszy, zawsze
WHEREkwotaISNULL-- tak sie to sprawdza
WHEREkwotaISNOTNULL
COUNT(*)-- liczy wszystkie wiersze
COUNT(kolumna)-- pomija te z NULL
Zmiana danych
INSERT dodaje rekord, UPDATE zmienia dane, DELETE usuwa wiersze. Przed UPDATE lub DELETE sprawdź warunek WHERE odpowiadającym mu SELECT-em. Dane od użytkownika przekazuj jako parametry prepared statement (przykład w artykule o PHP), zamiast sklejać SQL z tekstu formularza.
Rozbiór zapytań krok po kroku, z pułapkami NULL i NOT IN, znajdziesz w artykule o SQL, a pełne zadania w arkuszach INF.03.