Głównym celem tego zadania jest ugruntowanie i znaczne rozszerzenie praktycznych umiejętności studenta w posługiwaniu się językiem SQL. Pracując na w pełni znormalizowanym, relacyjnym schemacie bazy danych `biblioteka`, student przejdzie od prostych zapytań do konstruowania złożonych, wielotabelowych kwerend, które rozwiązują realne problemy biznesowe. Zadanie to obejmuje pełne spektrum operacji: od zaawansowanego odpytywania danych z wykorzystaniem różnych typów złączeń (`JOIN`), agregacji (`GROUP BY`), filtrowania (`WHERE`, `HAVING`) i sortowania (`ORDER BY`), poprzez operacje manipulacji danymi (CRUD: `INSERT`, `UPDATE`, `DELETE`), aż po modyfikację samej struktury bazy danych w locie (`ALTER TABLE`). Dodatkowo, wprowadzone zostaną bardziej zaawansowane koncepcje, takie jak tworzenie widoków (`VIEW`) i indeksów (`INDEX`) w celu optymalizacji. Po ukończeniu tego zadania, student powinien czuć się swobodnie, tworząc złożone zapytania SQL, które efektywnie wydobywają i przetwarzają informacje z bazy danych.
Student, teraz już w roli dewelopera aplikacji bibliotecznej, otrzymuje serię zadań od swojego przełożonego, które wymagają od niego biegłości w SQL. Pierwsze zadanie to stworzenie raportu pokazującego listę wszystkich aktualnie wypożyczonych książek wraz z danymi czytelnika i datą wypożyczenia. Student wie, że te informacje są rozproszone w trzech tabelach, więc konstruuje zapytanie `SELECT` z dwoma złączeniami `JOIN`, elegancko łącząc dane z tabel `wypozyczenia`, `czytelnicy` i `ksiazki`. Następnie, otrzymuje prośbę o wygenerowanie listy "najbardziej aktywnych czytelników". To wymaga od niego użycia funkcji agregującej `COUNT()` do policzenia wypożyczeń dla każdego czytelnika, a następnie użycia klauzuli `GROUP BY` do zgrupowania wyników i `ORDER BY ... DESC` do posortowania ich od najlepszego wyniku. Kolejne zadanie jest bardziej operacyjne: bibliotekarz prosi o zaktualizowanie statusu wypożyczenia dla książki, która właśnie została zwrócona. Student używa polecenia `UPDATE`, precyzyjnie identyfikując odpowiedni wiersz w tabeli `wypozyczenia` za pomocą klauzuli `WHERE`. Chwilę później dzwoni czytelnik, który chce usunąć swoje konto. Student próbuje wykonać polecenie `DELETE` na tabeli `czytelnicy`, ale serwer zwraca błąd. Po chwili analizy student orientuje się, że to działanie więzów integralności – nie można usunąć czytelnika, który ma na koncie aktywne wypożyczenia. To dla niego cenna, praktyczna lekcja o sile relacyjnego modelu. W międzyczasie pojawia się nowa potrzeba biznesowa: w systemie brakuje informacji o wydawnictwach książek. Student, bez przerywania pracy aplikacji, wykonuje polecenie `ALTER TABLE ksiazki ADD COLUMN wydawnictwo VARCHAR(150);`, dynamicznie rozszerzając strukturę bazy. Ponieważ zapytanie o aktywne wypożyczenia jest wykonywane bardzo często, student postanawia je zoptymalizować. Tworzy `VIEW` (widok) o nazwie `v_aktywne_wypozyczenia`, który enkapsuluje (zamyka w sobie) złożone zapytanie `JOIN`. Od teraz, aby uzyskać ten raport, wystarczy proste `SELECT * FROM v_aktywne_wypozyczenia`. Na koniec, zauważając, że wyszukiwanie czytelników po nazwisku działa wolno, zakłada `INDEX` na kolumnie `nazwisko` w tabeli `czytelnicy`, co, jak wie, drastycznie przyspieszy przyszłe operacje wyszukiwania.
Podstawą pracy z relacyjną bazą danych jest umiejętność łączenia informacji z wielu tabel. Poniższe zapytanie generuje kompleksowy raport o wypożyczeniach.
USE biblioteka;
-- Wybieramy imię i nazwisko czytelnika, tytuł książki i datę wypożyczenia.
-- Używamy aliasów (c, k, w) dla skrócenia zapisu i zwiększenia czytelności.
SELECT
    c.imie,
    c.nazwisko,
    k.tytul,
    w.data_wypozyczenia
FROM wypozyczenia AS w
JOIN czytelnicy AS c ON w.czytelnik_id = c.id
JOIN ksiazki AS k ON w.ksiazka_id = k.id
WHERE w.status = 'wypozyczona';
            Często potrzebujemy nie tylko surowych danych, ale ich podsumowań. Poniższe zapytanie znajduje czytelników, którzy wypożyczyli co najmniej 2 książki.
SELECT
    c.imie,
    c.nazwisko,
    COUNT(w.id) AS liczba_wypozyczen
FROM czytelnicy AS c
JOIN wypozyczenia AS w ON c.id = w.czytelnik_id
GROUP BY c.id, c.imie, c.nazwisko -- Grupujemy po ID, ale dodajemy imię i nazwisko, aby móc je wyświetlić
HAVING COUNT(w.id) >= 2
ORDER BY liczba_wypozyczen DESC;
            Zobaczmy, jak wyglądają podstawowe operacje modyfikacji danych w praktyce.
-- CREATE (C): Dodajemy nowego czytelnika.
INSERT INTO czytelnicy (imie, nazwisko, email) VALUES ('Barbara', 'Kowalska', 'b.kowalska@example.com');
-- READ (R): Odczytujemy dane nowej osoby (zakładając, że dostała ID=3).
SELECT * FROM czytelnicy WHERE id = 3;
-- UPDATE (U): Aktualizujemy status wypożyczenia o ID=1 na 'zwrocona'.
UPDATE wypozyczenia
SET status = 'zwrocona', data_rzeczywistego_zwrotu = CURDATE()
WHERE id = 1;
-- DELETE (D): Usuwamy książkę o ID=2 (zadziała tylko, jeśli nie jest powiązana z żadnym wypożyczeniem).
DELETE FROM ksiazki WHERE id = 2;
            Schemat bazy danych "żyje" i często wymaga modyfikacji w trakcie rozwoju aplikacji. `ALTER TABLE` jest narzędziem do tego służącym.
-- Dodanie nowej kolumny do tabeli 'ksiazki'. ALTER TABLE ksiazki ADD COLUMN liczba_stron INT AFTER tytul; -- Zmiana typu danych istniejącej kolumny. ALTER TABLE czytelnicy MODIFY COLUMN email VARCHAR(254) NOT NULL; -- Zmiana nazwy kolumny. ALTER TABLE pracownicy CHANGE COLUMN email adres_email VARCHAR(150);
To dwa ważne narzędzia do optymalizacji i upraszczania pracy z bazą danych.
-- Tworzymy widok, który ukrywa złożoność zapytania JOIN.
CREATE VIEW v_pelny_katalog AS
SELECT
    k.tytul,
    k.rok_wydania,
    a.imie,
    a.nazwisko
FROM ksiazki k
JOIN ksiazki_autorzy ka ON k.id = ka.ksiazka_id
JOIN autorzy a ON ka.autor_id = a.id;
-- Teraz możemy odpytywać widok jak zwykłą tabelę.
SELECT * FROM v_pelny_katalog WHERE nazwisko = 'Tolkien';
-- Tworzymy indeks na kolumnie 'tytul', aby przyspieszyć wyszukiwanie książek.
CREATE INDEX idx_tytul ON ksiazki(tytul);
            Opanowanie języka SQL jest procesem ciągłym, ale to zadanie stanowi solidny fundament, który pozwala na swobodną i efektywną pracę z danymi. Zrozumieliśmy, że siła relacyjnych baz danych tkwi nie w przechowywaniu danych w izolowanych tabelach, ale w możliwości ich dynamicznego łączenia (`JOIN`) w celu tworzenia użytecznych informacji. Nauczyliśmy się, jak wyjść poza proste odpytywanie i wykonywać złożone analizy z użyciem funkcji agregujących i grupowania, co jest podstawą każdego raportowania i analityki biznesowej. Kluczowym wnioskiem jest to, że SQL to język kompletny – pozwala nie tylko na odczyt i modyfikację danych (DML - Data Manipulation Language), ale także na dynamiczne zarządzanie strukturą samej bazy (DDL - Data Definition Language). Wprowadzenie do widoków i indeksów otworzyło nam oczy na kwestie optymalizacji i bezpieczeństwa. Widoki upraszczają złożoność i pozwalają na kontrolę dostępu, podczas gdy indeksy są najważniejszym narzędziem w walce o wydajność aplikacji. Biegłość w tworzeniu zapytań, świadomość konsekwencji każdej operacji modyfikującej oraz umiejętność optymalizacji schematu to kompetencje, które definiują profesjonalnego dewelopera i administratora baz danych.