Lekcja 10. Rodzaje relacji w praktyce — pełna implementacja 1:1, 1:N, N:M
ŚredniPo co się tego uczymy?
Znać teorię relacji to jedno, ale na egzaminie i w prawdziwej pracy musisz umieć NAPISAĆ kod SQL, który poprawnie implementuje każdy z trzech typów. Kluczowa różnica leży w jednym małym słowie — UNIQUE.
Teoria
W lekcji o modelu E-R poznałeś teoretycznie trzy typy relacji. Teraz zaimplementujemy WSZYSTKIE TRZY naraz w jednej, spójnej bazie szkolnej — żebyś zobaczył różnicę w konkretnym kodzie SQL, nie tylko na obrazku.
1:1 — UCZEŃ ↔ LEGITYMACJA. Klucz obcy z więzem UNIQUE w tabeli "słabszej" gwarantuje, że jeden uczeń ma dokładnie jedną legitymację.
1:N — KLASA → UCZNIOWIE. Zwykły klucz obcy (bez UNIQUE) w tabeli "wielu" — jedna klasa, wielu uczniów.
N:M — UCZNIOWIE ↔ PRZEDMIOTY. Wymaga tabeli pośredniczącej (tutaj: OCENY) z dwoma kluczami obcymi — do ucznia i do przedmiotu.
Schemat
Przykład z życia
Dziennik elektroniczny szkoły w jednej bazie ma wszystkie trzy typy relacji naraz: uczeń ma jedną legitymację (1:1), należy do jednej klasy (1:N), ale ma oceny z wielu przedmiotów, a każdy przedmiot ma ocenianych wielu uczniów (N:M).
Kod (SQL)
CREATE DATABASE IF NOT EXISTS szkola_relacje;
USE szkola_relacje;
-- 1:N — jedna klasa, wielu uczniów
CREATE TABLE Klasy (
id_klasy INT AUTO_INCREMENT PRIMARY KEY,
nazwa VARCHAR(10) NOT NULL
);
CREATE TABLE Uczniowie (
id_ucznia INT AUTO_INCREMENT PRIMARY KEY,
imie VARCHAR(50) NOT NULL,
nazwisko VARCHAR(60) NOT NULL,
id_klasy INT NOT NULL,
FOREIGN KEY (id_klasy) REFERENCES Klasy(id_klasy)
);
-- 1:1 — jeden uczeń, dokładnie jedna legitymacja (UNIQUE na kluczu obcym!)
CREATE TABLE Legitymacje (
id_legitymacji INT AUTO_INCREMENT PRIMARY KEY,
nr_legitymacji VARCHAR(20) NOT NULL UNIQUE,
id_ucznia INT NOT NULL UNIQUE,
FOREIGN KEY (id_ucznia) REFERENCES Uczniowie(id_ucznia)
);
-- N:M — wielu uczniów ma wiele przedmiotów, realizowane przez tabelę Oceny
CREATE TABLE Przedmioty (
id_przedmiotu INT AUTO_INCREMENT PRIMARY KEY,
nazwa VARCHAR(50) NOT NULL
);
CREATE TABLE Oceny (
id_ucznia INT NOT NULL,
id_przedmiotu INT NOT NULL,
ocena DECIMAL(2,1) NOT NULL,
PRIMARY KEY (id_ucznia, id_przedmiotu, ocena),
FOREIGN KEY (id_ucznia) REFERENCES Uczniowie(id_ucznia),
FOREIGN KEY (id_przedmiotu) REFERENCES Przedmioty(id_przedmiotu)
);
Komentarz i wyjaśnienie kodu
Największa pułapka to różnica między 1:N a 1:1 w kodzie SQL — wygląda niemal identycznie, oba używają FOREIGN KEY! Różnicę robi dodatkowy więz UNIQUE na kolumnie id_ucznia w tabeli Legitymacje — to on wymusza, że jeden uczeń nie może mieć dwóch legitymacji. Bez tego UNIQUE byłaby to zwykła relacja 1:N (jeden uczeń, wiele legitymacji), co nie ma sensu biznesowego. Tabela Oceny to klasyczna tabela pośrednicząca dla N:M — ma dwa klucze obce, po jednym do każdej z łączonych tabel.
Ćwiczenie samodzielne
Wstaw przykładowe dane (2 klasy, 4 uczniów, 2 przedmioty, kilka ocen) i napisz zapytanie JOIN pokazujące imię ucznia, nazwę przedmiotu i ocenę.
Zadania do pracy własnej
Zadanie 1. Relacje 1:N i 1:1 w szkole
Uwaga przed importem: plik z bazą jest spakowany jako
.gz. phpMyAdmin w XAMPP przyjmuje takie pliki bez rozpakowywania. Jeżeli po pobraniu nazwa wygląda np.sklep_muzyczny.sql_.gzi import nie przejdzie, zmień nazwę pliku nasklep_muzyczny.sql.gz, a potem wybierz go w zakładce Importuj.Baza do pracy: Szkoła relacje (.sql.gz). Zaimportuj spakowany plik SQL w XAMPP/phpMyAdmin, a następnie wykonaj zapytania.
- Wyświetl uczniów wraz z nazwą klasy.
- Wyświetl uczniów wraz z numerem legitymacji.
- Wyświetl uczniów i przedmioty, na które uczęszczają.
- Policz uczniów w każdej klasie.
- Policz ilu uczniów ma każdy przedmiot.
- Wyświetl uczniów z klasy 1P i ich przedmioty.
- Wyświetl klasy wraz z wychowawcą i liczbą uczniów.
- Wyświetl uczniów, którzy mają więcej niż jeden przedmiot.
- Wyświetl przedmioty, na które nie zapisano żadnego ucznia.
- Wyświetl pełny raport: klasa, uczeń, legitymacja, przedmiot.
Zadanie 2. Relacje w sklepie muzycznym
Uwaga przed importem: plik z bazą jest spakowany jako
.gz. phpMyAdmin w XAMPP przyjmuje takie pliki bez rozpakowywania. Jeżeli po pobraniu nazwa wygląda np.sklep_muzyczny.sql_.gzi import nie przejdzie, zmień nazwę pliku nasklep_muzyczny.sql.gz, a potem wybierz go w zakładce Importuj.Baza do pracy: Sklep muzyczny (.sql.gz). Zaimportuj spakowany plik SQL w XAMPP/phpMyAdmin, a następnie wykonaj zapytania.
- Wyświetl zamówienia: imię, nazwisko, produkt, ilość, data.
- Wyświetl zamówienia wraz z kategorią produktu.
- Wyświetl klientów i produkty kupione po 1 października 2025.
- Wyświetl produkty, które zostały zamówione przez klientów z Gdańska.
- Wyświetl klienta, produkt i wartość pozycji zamówienia: ilość * cena.
- Wyświetl wszystkie produkty wraz z nazwą kategorii.
- Wyświetl klientów, którzy kupili instrumenty.
- Wyświetl zamówienia posortowane według nazwiska klienta i daty.
- Wyświetl klienta, miasto, produkt i kategorię dla każdego zamówienia.
- Wyświetl produkty zamówione w liczbie większej niż 2 sztuki.
Zadanie 3. Relacje N:M w siłowni
Uwaga przed importem: plik z bazą jest spakowany jako
.gz. phpMyAdmin w XAMPP przyjmuje takie pliki bez rozpakowywania. Jeżeli po pobraniu nazwa wygląda np.sklep_muzyczny.sql_.gzi import nie przejdzie, zmień nazwę pliku nasklep_muzyczny.sql.gz, a potem wybierz go w zakładce Importuj.Baza do pracy: Siłownia FitZone (.sql.gz). Zaimportuj spakowany plik SQL w XAMPP/phpMyAdmin, a następnie wykonaj zapytania.
- Wyświetl zajęcia wraz z imieniem i nazwiskiem trenera.
- Wyświetl klientów z karnetem Premium.
- Policz liczbę zajęć prowadzonych przez każdego trenera.
- Policz zapisy na każde zajęcia.
- Wyświetl klientów zapisanych na Trening siłowy.
- Pokaż zajęcia rozpoczynające się po godzinie 17:00.
- Pokaż klientów, którzy zapisali się na więcej niż jedne zajęcia.
- Wyświetl raport: klient, typ karnetu, zajęcia, trener, data zapisu.
- Policz zapisy według dnia.
- Pokaż trenerów, którzy prowadzą zajęcia z co najmniej dwoma zapisami.
Typowe błędy
Najczęstszy błąd to zapomnienie UNIQUE przy próbie zrobienia relacji 1:1 — bez tego baza pozwoli przypisać wielu uczniom tę samą legitymację albo jednemu uczniowi kilka legitymacji. Drugi błąd to próba zrobienia N:M przez dodanie dwóch kolumn z listami id (np. "id_przedmiotow: 1,2,3") zamiast osobnej tabeli — to łamie podstawową zasadę relacyjnych baz danych (1NF, patrz lekcja o normalizacji).
Nawiązanie do egzaminu zawodowego
To bezpośrednie ćwiczenie efektu INF.03.4.2 ("tworzy diagramy E/R", "definiuje związki między encjami i określa ich liczebność") — w informatorze CKE pojawia się dokładnie pytanie o rozpoznanie typu relacji z symbolu na diagramie E/R.