Dataczwartek, 13 sierpnia 2026 Czas18:50:39
← Bazy danych i SQL

Lekcja 10. Rodzaje relacji w praktyce — pełna implementacja 1:1, 1:N, N:M

Średni

Po 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

UCZEŃ LEGITYMACJA 1:1 KLASA UCZNIOWIE 1:N UCZNIOWIE PRZEDMIOTY OCENY N:M

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

  1. 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_.gz i import nie przejdzie, zmień nazwę pliku na sklep_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.

    1. Wyświetl uczniów wraz z nazwą klasy.
    2. Wyświetl uczniów wraz z numerem legitymacji.
    3. Wyświetl uczniów i przedmioty, na które uczęszczają.
    4. Policz uczniów w każdej klasie.
    5. Policz ilu uczniów ma każdy przedmiot.
    6. Wyświetl uczniów z klasy 1P i ich przedmioty.
    7. Wyświetl klasy wraz z wychowawcą i liczbą uczniów.
    8. Wyświetl uczniów, którzy mają więcej niż jeden przedmiot.
    9. Wyświetl przedmioty, na które nie zapisano żadnego ucznia.
    10. Wyświetl pełny raport: klasa, uczeń, legitymacja, przedmiot.
  2. 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_.gz i import nie przejdzie, zmień nazwę pliku na sklep_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.

    1. Wyświetl zamówienia: imię, nazwisko, produkt, ilość, data.
    2. Wyświetl zamówienia wraz z kategorią produktu.
    3. Wyświetl klientów i produkty kupione po 1 października 2025.
    4. Wyświetl produkty, które zostały zamówione przez klientów z Gdańska.
    5. Wyświetl klienta, produkt i wartość pozycji zamówienia: ilość * cena.
    6. Wyświetl wszystkie produkty wraz z nazwą kategorii.
    7. Wyświetl klientów, którzy kupili instrumenty.
    8. Wyświetl zamówienia posortowane według nazwiska klienta i daty.
    9. Wyświetl klienta, miasto, produkt i kategorię dla każdego zamówienia.
    10. Wyświetl produkty zamówione w liczbie większej niż 2 sztuki.
  3. 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_.gz i import nie przejdzie, zmień nazwę pliku na sklep_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.

    1. Wyświetl zajęcia wraz z imieniem i nazwiskiem trenera.
    2. Wyświetl klientów z karnetem Premium.
    3. Policz liczbę zajęć prowadzonych przez każdego trenera.
    4. Policz zapisy na każde zajęcia.
    5. Wyświetl klientów zapisanych na Trening siłowy.
    6. Pokaż zajęcia rozpoczynające się po godzinie 17:00.
    7. Pokaż klientów, którzy zapisali się na więcej niż jedne zajęcia.
    8. Wyświetl raport: klient, typ karnetu, zajęcia, trener, data zapisu.
    9. Policz zapisy według dnia.
    10. 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.