Wyobraź sobie, że Twoja książka adresowa ma tylko jedno pole: "Dane". Wpisujesz tam wszystko: "Jan Kowalski, ul. Miła 5, tel. 500-600-700, urodziny 15 maja". Jak znaleźć wszystkich, którzy mają urodziny w maju? Albo wszystkich mieszkających przy ulicy Miłej? Byłoby to bardzo trudne.
Dlatego aplikacja do kontaktów ma osobne pola: "Imię", "Nazwisko", "Ulica", "Numer telefonu", "Data urodzin". Dzięki temu możesz łatwo sortować i wyszukiwać kontakty.
Nasza pierwsza tabela, czytelnicy_denormalized, jest jak ta książka adresowa z jednym polem. Czas to naprawić, tworząc nowe, wyspecjalizowane tabele dla książek i pracowników, gdzie każda informacja będzie miała swoją własną "szufladkę" (kolumnę).
Celem jest rozbudowa naszej bazy biblioteka o dwie kluczowe tabele: ksiazki i pracownicy. Nauczysz się, jak starannie projektować ich strukturę, dobierać odpowiednie typy danych i stosować ograniczenia (UNIQUE, ENUM, DEFAULT), aby zapewnić spójność i poprawność danych. Na koniec zaimportujesz duże zestawy danych, aby nasza baza stała się w pełni funkcjonalna.
Zanim napiszemy kod, zastanówmy się, jakie informacje o książce są nam potrzebne. Będą to: unikalny identyfikator, tytuł, autor, numer ISBN, rok wydania, kategoria i status. Upewnij się, że pracujesz w kontekście bazy biblioteka (USE biblioteka;).
CREATE TABLE ksiazki (
  id_ksiazki INT AUTO_INCREMENT PRIMARY KEY,
  tytul VARCHAR(255) NOT NULL,
  autor VARCHAR(255) NOT NULL,
  isbn VARCHAR(17) UNIQUE,
  rok_wydania YEAR NULL,
  kategoria VARCHAR(100) NULL,
  status ENUM('Dostępna', 'Wypożyczona', 'Wycofana') NOT NULL DEFAULT 'Dostępna'
);
    
    isbn VARCHAR(17) UNIQUE: ISBN to unikalny identyfikator książki. Ograniczenie UNIQUE działa jak strażnik – jeśli spróbujesz dodać drugą książkę z tym samym numerem ISBN, serwer zwróci błąd. To kluczowe dla utrzymania porządku w danych.rok_wydania YEAR NULL: Używamy typu YEAR, bo jest zoptymalizowany do przechowywania roku (zajmuje tylko 1 bajt pamięci). NULL oznacza, że pole jest opcjonalne – możemy mieć w bazie książkę, której roku wydania nie znamy.status ENUM(...) NOT NULL DEFAULT 'Dostępna': To bardzo potężna definicja. NOT NULL oznacza, że każda książka musi mieć status. DEFAULT 'Dostępna' oznacza, że jeśli dodamy nową książkę i nie określimy jej statusu, serwer automatycznie ustawi ją jako 'Dostępna'.Po wykonaniu powyższego polecenia, warto sprawdzić, czy serwer "zrozumiał" nasze intencje. Użyj polecenia SHOW CREATE TABLE, które pokaże dokładny kod SQL użyty do stworzenia tabeli.
SHOW CREATE TABLE ksiazki;
    Wynik będzie bardzo podobny do kodu, który napisaliśmy, co potwierdza, że tabela została utworzona zgodnie ze specyfikacją.
ksiazkiINSERT INTO ksiazki... z pliku źródłowego do pliku import_ksiazek.sql na Pulpicie.mysql -u root -p biblioteka < C:\Users\TwojaNazwaUzytkownika\Desktop\import_ksiazek.sql
Plik -> Wczytaj plik SQL....import_ksiazek.sql. Jego zawartość pojawi się w oknie zapytań.
-- Policzmy, ile dokładnie wierszy zostało zaimportowanych
SELECT COUNT(*) FROM ksiazki;
-- Wyświetlmy kilka losowych książek z kategorii "Science Fiction"
SELECT tytul, autor FROM ksiazki WHERE kategoria = 'Science Fiction' LIMIT 3;
      
    pracownicy
CREATE TABLE pracownicy (
  id_pracownika INT AUTO_INCREMENT PRIMARY KEY,
  imie VARCHAR(100) NOT NULL,
  nazwisko VARCHAR(100) NOT NULL,
  stanowisko VARCHAR(100) NOT NULL,
  data_zatrudnienia DATE NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE
);
    
    data_zatrudnienia DATE NOT NULL: Użycie typu DATE jest kluczowe. Przechowuje on datę w wewnętrznym, zoptymalizowanym formacie. Dzięki temu możemy wykonywać operacje na datach, np. SELECT * FROM pracownicy WHERE YEAR(data_zatrudnienia) = 2023;, co byłoby niemożliwe, gdyby data była przechowywana jako zwykły tekst.email VARCHAR(255) NOT NULL UNIQUE: Ponownie używamy UNIQUE, aby zagwarantować, że nie można dodać dwóch pracowników z tym samym adresem e-mail. To fundamentalna zasada integralności danych.Proces jest identyczny jak w przypadku książek. Przygotuj plik import_pracownikow.sql, zaimportuj go jedną z poznanych metod, a następnie zweryfikuj wynik.
-- Sprawdźmy, ilu mamy bibliotekarzy
SELECT COUNT(*) FROM pracownicy WHERE stanowisko = 'Bibliotekarz';
-- Znajdźmy najstarszego stażem pracownika
SELECT imie, nazwisko, data_zatrudnienia FROM pracownicy ORDER BY data_zatrudnienia ASC LIMIT 1;
    
  Doskonale! Twoja baza danych jest teraz znacznie bogatsza. Posiadasz trzy tabele, z których dwie (ksiazki i pracownicy) są dobrze zaprojektowane. Problem wciąż leży w naszej pierwszej tabeli:
[Tabela: czytelnicy_denormalized]
+--+----------------------------------+--------------------------------------------------+
|id| dane_osobowe                     | wypozyczenia                                     |
+--+----------------------------------+--------------------------------------------------+
| 1| Anna Nowak, anna.nowak@email.com | "1:Władca Pierścieni:2025-10-01;12:Diuna:2025-10-15"| <-- Zwykły tekst!
+--+----------------------------------+--------------------------------------------------+
[Tabela: ksiazki]
+----------+------------------------------------------+
|id_ksiazki| tytul                                    |
+----------+------------------------------------------+
| 1        | Władca Pierścieni: Drużyna Pierścienia |
| ...      | ...                                      |
| 12       | Diuna                                    |
+----------+------------------------------------------+
    
    Jak widać, kolumna wypozyczenia to tylko tekst. Baza danych nie wie, że "1" i "12" w tym tekście odnoszą się do konkretnych książek w tabeli ksiazki. Nie możemy łatwo sprawdzić, kto wypożyczył "Diunę".
W następnym zadaniu rozwiążemy ten problem, przeprowadzając normalizację tabeli czytelników i tworząc między tabelami relacje za pomocą kluczy obcych. To serce projektowania relacyjnych baz danych!