Ćwiczenia SQL — baza: schronisko

Podstawy SQL — Schronisko

Ćwiczenie 1 — Utworzenie bazy i tabeli zwierzeta

Polecenie: Utwórz bazę danych schronisko oraz tabelę zwierzeta z polami: id (PK), imie, gatunek, wiek, status (np. 'w_schronisku', 'adoptowany').

CREATE DATABASE IF NOT EXISTS schronisko;
USE schronisko;

CREATE TABLE zwierzeta (
  id INT AUTO_INCREMENT PRIMARY KEY,
  imie VARCHAR(50) NOT NULL,
  gatunek VARCHAR(30) NOT NULL,
  wiek INT,
  status VARCHAR(20) DEFAULT 'w_schronisku'
);
    

Uwaga: nazwy tabel i pól bez polskich znaków (łatwiej w SQL).

Ćwiczenie 2 — Tabele wlasciciele i adopcje

Polecenie: Dodaj tabelę wlasciciele (id, imie, nazwisko, telefon) oraz tabelę adopcje (id, zwierze_id, wlasciciel_id, data_adopcji) z kluczami obcymi.

CREATE TABLE wlasciciele (
  id INT AUTO_INCREMENT PRIMARY KEY,
  imie VARCHAR(50),
  nazwisko VARCHAR(50),
  telefon VARCHAR(20)
);

CREATE TABLE adopcje (
  id INT AUTO_INCREMENT PRIMARY KEY,
  zwierze_id INT,
  wlasciciel_id INT,
  data_adopcji DATE,
  FOREIGN KEY (zwierze_id) REFERENCES zwierzeta(id),
  FOREIGN KEY (wlasciciel_id) REFERENCES wlasciciele(id)
);
    

Ćwiczenie 3 — Wstawianie przykładowych danych

Polecenie: Wstaw kilka zwierząt i właścicieli, aby mieć dane do ćwiczeń.

-- przykładowe zwierzęta
INSERT INTO zwierzeta (imie, gatunek, wiek, status) VALUES
('Burek','pies',3,'w_schronisku'),
('Maja','kot',2,'w_schronisku'),
('Rex','pies',8,'w_schronisku'),
('Kicia','kot',5,'adoptowany'),
('Saba','pies',6,'w_schronisku');

-- przykładowi właściciele
INSERT INTO wlasciciele (imie, nazwisko, telefon) VALUES
('Anna','Kowalska','600111222'),
('Jan','Nowak','600222333');
    

Ćwiczenie 4 — Proste SELECT-y

Polecenie: Napisz zapytania: (a) wszystkie zwierzęta, (b) wszystkie psy, (c) zwierzęta w wieku > 5.

-- a) wszystkie zwierzęta
SELECT * FROM zwierzeta;

-- b) tylko psy
SELECT * FROM zwierzeta WHERE gatunek = 'pies';

-- c) starsze niż 5 lat
SELECT * FROM zwierzeta WHERE wiek > 5;
    

Ćwiczenie 5 — UPDATE i DELETE

Polecenie: (a) Zaktualizuj status zwierzęcia o id = 3 na 'adoptowany'. (b) Usuń wpis o imieniu 'Saba'.

-- a) oznacz jako adoptowany
UPDATE zwierzeta SET status = 'adoptowany' WHERE id = 3;

-- b) usuń Saba
DELETE FROM zwierzeta WHERE imie = 'Saba';
    

Relacje & Zaawansowane — zapytania z JOIN, GROUP BY, widoki, trigger

Ćwiczenie 1 — JOIN: lista adopcji

Polecenie: Wyświetl listę adopcji: id adopcji, imię zwierzęcia, gatunek, imię i nazwisko właściciela, data adopcji.

SELECT a.id AS adopcja_id,
       z.imie AS zwierze_imie,
       z.gatunek,
       w.imie AS wlasciciel_imie,
       w.nazwisko AS wlasciciel_nazwisko,
       a.data_adopcji
FROM adopcje a
JOIN zwierzeta z ON a.zwierze_id = z.id
JOIN wlasciciele w ON a.wlasciciel_id = w.id;
    

Ćwiczenie 2 — LEFT JOIN: zwierzęta bez właściciela

Polecenie: Wyświetl wszystkie zwierzęta, które nie zostały jeszcze adoptowane (brak wpisu w adopcje).

SELECT z.id, z.imie, z.gatunek, z.status
FROM zwierzeta z
LEFT JOIN adopcje a ON z.id = a.zwierze_id
WHERE a.id IS NULL;
    

Ćwiczenie 3 — GROUP BY: liczba adopcji na właściciela

Polecenie: Dla każdego właściciela policz, ile zwierząt adoptował. Pokaż tylko właścicieli z co najmniej jedną adopcją.

SELECT w.id, w.imie, w.nazwisko, COUNT(a.id) AS liczba_adopcje
FROM wlasciciele w
JOIN adopcje a ON w.id = a.wlasciciel_id
GROUP BY w.id
HAVING COUNT(a.id) > 0;
    

Ćwiczenie 4 — Widok: dostępne zwierzęta

Polecenie: Stwórz widok dostepne_zwierzeta, który zwraca zwierzęta o statusie 'w_schronisku'.

CREATE VIEW dostepne_zwierzeta AS
SELECT id, imie, gatunek, wiek
FROM zwierzeta
WHERE status = 'w_schronisku';
    

Widok przydatny do szybkiego wyświetlania aktualnych zwierząt.

Ćwiczenie 5 — Trigger: ustaw status przy dodaniu adopcji

Polecenie: Napisz trigger, który po wstawieniu rekordu do tabeli adopcje ustawi status zwierzęcia na 'adoptowany'. (MySQL)

DELIMITER //
CREATE TRIGGER po_dodaniu_adopcji
AFTER INSERT ON adopcje
FOR EACH ROW
BEGIN
  UPDATE zwierzeta
  SET status = 'adoptowany'
  WHERE id = NEW.zwierze_id;
END;
//
DELIMITER ;
    

SQL + PHP — formularze i skrypty

Ćwiczenie 1 — Formularz dodawania zwierzęcia (PHP)

Polecenie: Stwórz formularz w PHP do dodawania nowego zwierzęcia do tabeli zwierzeta. Użyj prostego sprawdzenia danych.

<form method="post">
  Imię: <input name="imie"><br>
  Gatunek: <input name="gatunek"><br>
  Wiek: <input type="number" name="wiek"><br>
  <input type="submit" value="Dodaj zwierzę">
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $imie = $_POST['imie'];
  $gatunek = $_POST['gatunek'];
  $wiek = (int)$_POST['wiek'];
  $conn = new mysqli('localhost','root','','schronisko');
  $stmt = $conn->prepare("INSERT INTO zwierzeta (imie,gatunek,wiek) VALUES (?, ?, ?)");
  $stmt->bind_param('ssi', $imie, $gatunek, $wiek);
  $stmt->execute();
  $stmt->close();
  $conn->close();
  echo "Dodano zwierzę: $imie";
}
?>
    

Użyj prepared statements (bezpieczeństwo).

Ćwiczenie 2 — Wyszukiwanie zwierząt (bezpieczne)

Polecenie: Zaimplementuj wyszukiwarkę po imieniu (GET) i wyświetl dopasowania. Użyj przygotowanego zapytania (prepared statement).

<form method="get">
  Szukaj imienia: <input name="q">
  <input type="submit" value="Szukaj">
</form>

<?php
if (isset($_GET['q'])) {
  $q = "%".$_GET['q']."%";
  $conn = new mysqli('localhost','root','','schronisko');
  $stmt = $conn->prepare("SELECT id, imie, gatunek FROM zwierzeta WHERE imie LIKE ?");
  $stmt->bind_param('s', $q);
  $stmt->execute();
  $res = $stmt->get_result();
  while ($row = $res->fetch_assoc()) {
    echo $row['id']." - ".$row['imie']." (".$row['gatunek'].")<br>";
  }
  $stmt->close(); $conn->close();
}
?>
    

Ćwiczenie 3 — Formularz adopcji (transakcja PHP)

Polecenie: Zaimplementuj formularz, który przyjmie zwierze_id i wlasciciel_id, doda wpis do adopcje i zaktualizuje status zwierzęcia w jednej transakcji.

<form method="post">
  Zwierze ID: <input name="zwierze_id">
  Właściciel ID: <input name="wlasciciel_id">
  <input type="submit" value="Adoptuj">
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $zid = (int)$_POST['zwierze_id'];
  $wid = (int)$_POST['wlasciciel_id'];
  $conn = new mysqli('localhost','root','','schronisko');
  $conn->begin_transaction();
  try {
    $stmt = $conn->prepare("INSERT INTO adopcje (zwierze_id, wlasciciel_id, data_adopcji) VALUES (?, ?, CURDATE())");
    $stmt->bind_param('ii', $zid, $wid);
    $stmt->execute();
    $stmt->close();
    $stmt2 = $conn->prepare("UPDATE zwierzeta SET status = 'adoptowany' WHERE id = ?");
    $stmt2->bind_param('i', $zid);
    $stmt2->execute();
    $stmt2->close();
    $conn->commit();
    echo "Adopcja zakończona sukcesem.";
  } catch (Exception $e) {
    $conn->rollback();
    echo "Błąd przy adopcji: ".$e->getMessage();
  }
  $conn->close();
}
?>
    

Transakcja zapewnia spójność — albo wszystko wraca, albo zostaje zatwierdzone.

Ćwiczenie 4 — Proste logowanie dla pracowników (bezpieczeństwo)

Polecenie: Stwórz tabelę uzytkownicy i prosty schemat logowania z hash'owaniem haseł (password_hash / password_verify).

CREATE TABLE uzytkownicy (
  id INT AUTO_INCREMENT PRIMARY KEY,
  login VARCHAR(50) UNIQUE,
  haslo VARCHAR(255)
);

-- rejestracja (raz, np. w konsoli PHP):
-- $hash = password_hash('tajneHaslo', PASSWORD_DEFAULT);
-- INSERT INTO uzytkownicy (login, haslo) VALUES('pracownik','<tu_hash>');

<!-- fragment logowania -->
<form method="post">
  Login: <input name="login">
  Hasło: <input type="password" name="haslo">
  <input type="submit">
</form>

<?php
// sprawdzenie
$conn = new mysqli('localhost','root','','schronisko');
$stmt = $conn->prepare("SELECT haslo FROM uzytkownicy WHERE login = ?");
$stmt->bind_param('s', $_POST['login']);
$stmt->execute();
$res = $stmt->get_result();
if ($row = $res->fetch_assoc()) {
  if (password_verify($_POST['haslo'], $row['haslo'])) {
    echo "Zalogowano!";
  } else echo "Błędne hasło";
}
$stmt->close(); $conn->close();
?>
    

Nie trzymaj haseł w czystym tekście — zawsze hashuj.

Ćwiczenie 5 — Raport: adopcje miesięczne (GROUP BY w PHP)

Polecenie: Napisz zapytanie zwracające liczbę adopcji w kolejnych miesiącach (rok bieżący) i wyświetl wynik w PHP.

-- SQL
SELECT DATE_FORMAT(data_adopcji, '%Y-%m') AS miesiac, COUNT(*) AS liczba
FROM adopcje
WHERE YEAR(data_adopcji) = YEAR(CURDATE())
GROUP BY DATE_FORMAT(data_adopcji, '%Y-%m')
ORDER BY miesiac;

-- przykładowy fragment PHP do wyświetlenia:
<?php
$conn = new mysqli('localhost','root','','schronisko');
$res = $conn->query("SELECT DATE_FORMAT(data_adopcji,'%Y-%m') AS miesiac, COUNT(*) AS liczba FROM adopcje WHERE YEAR(data_adopcji)=YEAR(CURDATE()) GROUP BY DATE_FORMAT(data_adopcji,'%Y-%m') ORDER BY miesiac");
while ($r = $res->fetch_assoc()) {
  echo $r['miesiac']." : ".$r['liczba']."<br>";
}
$conn->close();
?>
    

Ćwiczenie 1: Wyświetlanie wszystkich zwierząt

Wypisz wszystkie rekordy z tabeli Zwierzęta.

Ćwiczenie 2: Filtrowanie według gatunku

Wyświetl wszystkie koty z tabeli Zwierzęta.