0. Inicjalizacja bazy sklep (przypomnienie)
Jeśli nie masz jeszcze bazy sklep i głównych tabel, wykonaj ten blok w phpMyAdmin (zakładka SQL).
Pokaż kod DDL (baza + główne tabele)
CREATE DATABASE IF NOT EXISTS sklep
CHARACTER SET utf8mb4
COLLATE utf8mb4_polish_ci;
USE sklep;
CREATE TABLE IF NOT EXISTS klienci (
id_klienta INT AUTO_INCREMENT PRIMARY KEY,
imie VARCHAR(50),
nazwisko VARCHAR(50),
email VARCHAR(100),
telefon VARCHAR(20),
adres VARCHAR(255),
vip BOOLEAN DEFAULT 0,
rabat DECIMAL(5,2) DEFAULT 0.00
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
CREATE TABLE IF NOT EXISTS zamowienia (
id_zamowienia INT AUTO_INCREMENT PRIMARY KEY,
id_klienta INT,
data_zamowienia DATE,
wartosc_zamowienia DECIMAL(10,2),
metoda_platnosci ENUM('Gotowka','Karta','Przelew'),
status ENUM('Nowe','Realizacja','Zakonczone','VIP') DEFAULT 'Nowe',
FOREIGN KEY (id_klienta) REFERENCES klienci(id_klienta)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
CREATE TABLE IF NOT EXISTS produkty (
id_produktu INT AUTO_INCREMENT PRIMARY KEY,
nazwa VARCHAR(100),
cena DECIMAL(10,2),
kategoria VARCHAR(50)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
CREATE TABLE IF NOT EXISTS szczegoly_zamowienia (
id_szczegolu INT AUTO_INCREMENT PRIMARY KEY,
id_zamowienia INT,
id_produktu INT,
ilosc INT,
FOREIGN KEY (id_zamowienia) REFERENCES zamowienia(id_zamowienia),
FOREIGN KEY (id_produktu) REFERENCES produkty(id_produktu)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
Po utworzeniu struktury możesz wczytać dane testowe z poprzednich stron (klienci, zamówienia, produkty, szczegóły).
Ćwiczenia 16–20: Rozszerzanie Struktury Danych (DDL)
Ćwiczenie 16: Dodanie tabeli płatności
Zadanie: Stwórz tabelę platnosci przechowującą szczegóły płatności za zamówienia (kwota, metoda, data, powiązanie z zamowienia).
Pokaż rozwiązanie DDL
CREATE TABLE IF NOT EXISTS platnosci (
id_platnosci INT AUTO_INCREMENT PRIMARY KEY,
id_zamowienia INT NOT NULL,
data_platnosci DATETIME DEFAULT CURRENT_TIMESTAMP,
kwota DECIMAL(10,2) NOT NULL,
metoda_platnosci ENUM('Gotowka','Karta','Przelew') NOT NULL,
FOREIGN KEY (id_zamowienia) REFERENCES zamowienia(id_zamowienia)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
Użycie DATETIME DEFAULT CURRENT_TIMESTAMP pozwala automatycznie zapisać moment płatności; ENUM ogranicza metody do ustalonej listy.
Ćwiczenie 17: Dodanie historii zamówień
Zadanie: Stwórz tabelę historia_zamowien logującą zmiany statusu zamówień.
Pokaż rozwiązanie DDL
CREATE TABLE IF NOT EXISTS historia_zamowien (
id_historii INT AUTO_INCREMENT PRIMARY KEY,
id_zamowienia INT NOT NULL,
zmiana_statusu ENUM('Nowe','Realizacja','Zakonczone','Anulowane','VIP') NOT NULL,
data_zmiany TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (id_zamowienia) REFERENCES zamowienia(id_zamowienia)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
Każdy wpis w historii mówi, jaki status został ustawiony i kiedy – przydatne do audytu i raportów SLA.
Ćwiczenie 18: 10 najdroższych zamówień
Zadanie: Wyświetl 10 najdroższych zamówień.
Pokaż rozwiązanie DQL
SELECT *
FROM zamowienia
ORDER BY wartosc_zamowienia DESC
LIMIT 10;
ORDER BY ... DESC sortuje od najwyższej kwoty, a LIMIT 10 ogranicza wynik do top 10.
Ćwiczenie 19: Tabela kuponów rabatowych
Zadanie: Stwórz tabelę kupony z unikalnym kodem, rabatem i datą ważności.
Pokaż rozwiązanie DDL
CREATE TABLE IF NOT EXISTS kupony (
id_kuponu INT AUTO_INCREMENT PRIMARY KEY,
kod_kuponu VARCHAR(50) UNIQUE,
rabat DECIMAL(5,2) NOT NULL,
data_waznosci DATE NOT NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_polish_ci;
UNIQUE na kod_kuponu uniemożliwia duplikaty, a DECIMAL(5,2) dobrze nadaje się na rabat w procentach lub kwocie.
Ćwiczenie 20: Powiązanie kuponów z zamówieniami
Zadanie: Dodaj do zamowienia kolumnę id_kuponu jako klucz obcy.
Pokaż rozwiązanie DDL
ALTER TABLE zamowienia
ADD COLUMN id_kuponu INT NULL;
ALTER TABLE zamowienia
ADD CONSTRAINT fk_zamowienia_kupony
FOREIGN KEY (id_kuponu) REFERENCES kupony(id_kuponu);
Dzięki temu możesz analizować, jak kupony wpływają na sprzedaż (np. ile zamówień użyło danego kodu).
Ćwiczenia 21–24: Operacje DML i Złożone Zapytania (DQL)
Ćwiczenie 21: Aktualizacja cen produktów
Zadanie: Podnieś ceny produktów w kategorii 'Elektronika' o 10%.
Pokaż rozwiązanie DML
UPDATE produkty
SET cena = cena * 1.10
WHERE kategoria = 'Elektronika';
Uważaj na powtórne wykonywanie – każde uruchomienie dodaje kolejne 10%, to nie jest operacja idempotentna.
Ćwiczenie 22: Liczba produktów w zamówieniu
Zadanie: Dla każdego zamówienia policz, ile pozycji (produktów) się w nim znajduje.
Pokaż rozwiązanie DQL
SELECT z.id_zamowienia,
COUNT(sz.id_produktu) AS liczba_produktow
FROM zamowienia z
JOIN szczegoly_zamowienia sz
ON z.id_zamowienia = sz.id_zamowienia
GROUP BY z.id_zamowienia;
Liczymy liczbę pozycji w koszyku, nie ilość sztuk – do zliczania sztuk można użyć SUM(ilosc) zamiast COUNT().
Ćwiczenie 23: Zamówienia z rabatem klienta
Zadanie: Wyświetl zamówienia złożone przez klientów z rabatem > 0, wraz z rabatem.
Pokaż rozwiązanie DQL
SELECT z.id_zamowienia,
z.wartosc_zamowienia,
k.rabat
FROM zamowienia z
JOIN klienci k
ON z.id_klienta = k.id_klienta
WHERE k.rabat > 0;
Na bazie tego wyniku można obliczać np. „utracony” przychód przez udzielone rabaty.
Ćwiczenie 24: Usuwanie kuponów wygasłych
Zadanie: Usuń kupony, których data ważności minęła.
Pokaż rozwiązanie DML
DELETE FROM kupony
WHERE data_waznosci < CURDATE();
CURDATE() zwraca dzisiejszą datę w formacie YYYY‑MM‑DD, więc warunek usuwa wszystkie kupony starsze niż dziś.
Ćwiczenie 24.1: Top klienci wg wartości zamówień
Zadanie: Wyświetl 5 klientów o największej łącznej wartości zamówień (ID, imię, nazwisko, suma).
Pokaż rozwiązanie DQL
SELECT k.id_klienta,
k.imie,
k.nazwisko,
SUM(z.wartosc_zamowienia) AS suma_zamowien
FROM klienci k
JOIN zamowienia z
ON k.id_klienta = z.id_klienta
GROUP BY k.id_klienta, k.imie, k.nazwisko
ORDER BY suma_zamowien DESC
LIMIT 5;
Ćwiczenie 24.2: Lista zamówień z nazwami produktów
Zadanie: Wyświetl listę zamówień z wypisanymi nazwami produktów oraz ilością.
Pokaż rozwiązanie DQL
SELECT z.id_zamowienia,
p.nazwa,
sz.ilosc,
z.data_zamowienia
FROM zamowienia z
JOIN szczegoly_zamowienia sz
ON z.id_zamowienia = sz.id_zamowienia
JOIN produkty p
ON sz.id_produktu = p.id_produktu
ORDER BY z.id_zamowienia, p.nazwa;
Ćwiczenie 25: Procedury Składowane (Automatyzacja)
Ćwiczenie 25: Procedura dodawania produktu do zamówienia
Zadanie: Stwórz procedurę DodajProduktDoZamowienia, która wstawia rekordu do szczegoly_zamowienia.
Pokaż rozwiązanie (Procedura)
DELIMITER //
CREATE PROCEDURE DodajProduktDoZamowienia(
IN zamowienie_id INT,
IN produkt_id INT,
IN ilosc_sztuk INT
)
BEGIN
INSERT INTO szczegoly_zamowienia (id_zamowienia, id_produktu, ilosc)
VALUES (zamowienie_id, produkt_id, ilosc_sztuk);
END //
DELIMITER ;
Przykład wywołania: CALL DodajProduktDoZamowienia(1, 3, 2); – doda 2 sztuki produktu 3 do zamówienia 1.
Ćwiczenie 25.1: Procedura z automatycznym przeliczeniem wartości
Rozszerzenie: Zmodyfikuj procedurę, aby po dodaniu produktu przeliczała wartosc_zamowienia na podstawie cen produktów.
Pokaż przykładowe rozwiązanie
DELIMITER //
CREATE PROCEDURE DodajProduktDoZamowieniaAuto(
IN zamowienie_id INT,
IN produkt_id INT,
IN ilosc_sztuk INT
)
BEGIN
DECLARE cena_prod DECIMAL(10,2);
DECLARE nowa_wartosc DECIMAL(10,2);
-- 1. dodaj pozycje
INSERT INTO szczegoly_zamowienia (id_zamowienia, id_produktu, ilosc)
VALUES (zamowienie_id, produkt_id, ilosc_sztuk);
-- 2. pobierz cene produktu
SELECT cena INTO cena_prod
FROM produkty
WHERE id_produktu = produkt_id;
-- 3. przelicz wartosc zamowienia
SELECT wartosc_zamowienia + (cena_prod * ilosc_sztuk)
INTO nowa_wartosc
FROM zamowienia
WHERE id_zamowienia = zamowienie_id;
UPDATE zamowienia
SET wartosc_zamowienia = nowa_wartosc
WHERE id_zamowienia = zamowienie_id;
END //
DELIMITER ;
Ta wersja pokazuje, jak procedura może obsłużyć zarówno logikę koszyka, jak i przeliczanie sumy zamówienia w jednym wywołaniu.