Wprowadzenie
Na dzisiejszych laboratoriach kontynujemy dalej zagadnienia związane z SQL. Do pracy na zajęciach wymagane są gotowe zadania z poprzednich zajęć. Jeśli pracujesz na nowym stanowisku, pobierz swoje repozytorium i uruchom PSQL na Dockerze. W następnym kroku, zademostrowane zostanie graficzne środowisko, dzięki któremu łatwo wykonamy skrypty z laboratorium04 i z którym będzie pracować przez resztę zajęć.
Konfiguracja zintegrowanego środowiska programistycznego dla baz danych
Instalacja
Na zajęciach będziemy pracować na IDE DataGrip od JetBrains. Narzędzie pozwala na pracę z wieloma DBMS na raz, lokalnie bądź zdalnie. Stanowiska laboratoryjne już posiadają zaintalowane oprogramowanie, wymagane jest natomiast wskazanie serwera licencji. Zostanie ono podane w czasie zajęć.
Natomiast dla studentów pracujących na własnych maszynach oraz do pracy z domu, udostępniam poniższą instrukcję:
- Pobierz ze strony JetBrains narzędzie DataGrip: link.
- Zainstaluj narzędzie
- Po uruchomieniu, program prosi o podanie licencji. Jeśli jej nie masz, możesz całkowicie za darmo ją uzyskać wypełniając ten formularz link. W formularzu podaj swój email uczelniany. Po weryfikacji, uzyskasz dostęp do pełnej gamy produktów firmy JetBrains (DataGrip, IntelliJ, Rider, ReSharper, PhpStorm, Webstorm itd.)
Połączenie z bazą danych
Uruchom środowisko. Podczas pierwszego uruchomienia oraz po wypełnieniu monitu z licencją, powinno pojawić się poniższe okno. Klikamy New Project
.
Następnie pojawi się okno dialogowe z opcją zdefiniowania nazwy projektu. Uzepełnij je wpisująć rbd
.
Po zatwierdzeniu pojawi się główny ekran środowiska DataGrip:
Aby skonfigurować połączenie wybierz znak plusa w Database Explorer
, który znajduje się po lewej stronie aplikacji. Następnie z rozwiniętego menu wybierz Data Source
, a następnie PostgresSQL
.
Po wykonaniu powyższej czynności, ukaże się okno konfiguracyjne połączenia z bazą danych:
Uzupełnij ją według poniższej instrukcji:
- Name:
taxi@localhost
- User: ‘postgres’
- Password:
lele
, bądź inne jeśli zdefiniowałeś swoje własne podczas tworzenia kontenera - Database:
taxi
, czyli nazwa stworzonej bazy danych z poprzednich zajęć
Okienko po wypełnieniu, powinno wyglądać tak:
Przejdź teraz do zakładki schema
. Zaznacz opcję All databases
.
Wróć do zakładki General
. Sprawdź połączenie z bazą klikając Test Connection
. Może być wymagane pobranie wcześniej dodatkowych sterowników. Jeśli ich nie posiadasz, środowisko automatycznie to wykryje i zaproponuje pobranie je za Ciebie. Monit o brakujących sterownikach wyświetli się powyżej Test Connection
. W takim przypadku należy kliknąć Download
. Po pobraniu jeszcze raz sprawdź połączenie. Jeśli wszystko zostało skonfigurowane poprawnie, pojawi się poniższy monit.
Po przetestowaniu połączenia kliknij przycisk Ok
.
Wgranie skryptów z poprzednich zajęć
W lewym oknie, kliknij prawym przyciskiem na bazę danych, a następnie wybierz New
a potem Query Console
Otworzy się okno, wklej do niego skrypty z poprzednich zajęć
Zaznacz wszystkie skrypty (używając skrótu klawiszego CTRL
+ A
) i kliknij przycisk zielonej strzałki (execute).
SQL part 2
Filtrowanie danych
WHERE
Podstawą filtrowania danych w SQL, jest dodanie klauzuli WHERE
do zapytania SELECT
z odpowiednim warunkiem.
Na przykład, dla tabeli adresowej, zapytanie o wszystkie ulice w Gdańsku, prezentowała by się następująco:
1
SELECT street_name FROM address WHERE city = 'Gdańsk';
Klauzula WHERE
może przyjąć wiele operatorów do warunków:
=
- równa się!=
- negacja / nie równa się>
- większe<
- mniejsze>=
- większe lub równe<=
- mniejsze lub równeBETWEEN
- wartości w przedzialeLIKE
- zbliżone wartości, które muszą zaczynać się lub kończyć na zdefiniowaną wartość. Wartości neatrulne oznaczone są tzw. wildcardem, czyli%
IN
- wartości w zdeklarowanej liście wartości
Dodatkowo klauzula WHERE
przyjmuje operatory logiczne, które pozwalają łączyć warunki:
AND
OR
NOT
Przykład zapytania o numery indeksów studentów, którzy nazywają się Jakub, Michał lub Arkadiusz, są urodzeni po 01.01.1995, zaczeli studia pomiędzy 2015 a 2019, nie skończyli studiów pomiędzy 2017 a 2020 i ich nazwisko kończy się na ‘ski’:
1
2
3
4
5
6
SELECT index_number FROM student
WHERE first_name IN ('Jakub', 'Michał', 'Arkadiusz')
AND date_of_birth > '1995-01-01'
AND study_start_year BETWEEN 2015 AND 2019
AND study_end_year NOT BETWEEN 2017 AND 2020
AND last_name LIKE '%ski';
Grupowanie danych
GROUP BY
Dzięki zastasowaniu klauzuli GROUP BY
jesteśmy w stanie zgrupować wiersze w tzw. wiersze podsumowujące. Przykładem zastasowania GROUP BY
może być zapytanie o liczbę studentów zapisanych na dany przedmiot. Klauzula GROUP BY
często stosowany jest razem z tzw. funkcjami agregującymi jak np. COUNT
, SUM
, AVG
, MIN
czy MAX
.
Przykład użycia:
1
2
3
SELECT COUNT(student_id), subject
FROM students
GROUP BY subject
HAVING
Minusem klauzuli GROUP BY
jest fakt niemożliwości łączenia go z klauzulą WHERE
przy funcjach agregujących. Rozwiązaniem problemu jest użycie klauzuli HAVING
.
Przykład:
1
2
3
4
SELECT COUNT(student_id), subject
FROM students
GROUP BY subject
HAVING COUNT(student_id) > 13784
Modyfikowanie danych
UPDATE
Do aktualizacji danych encji, używana jest komenda UPDATE
. Jednakże podczas używania tej komendy trzeba zachować ostrożność. Sformułowanie podanego poniżej zapytania:
1
UPDATE address SET city = 'Gdańsk';
spowoduje że dla wszystkich rekordów w tabeli adress, zostanie ustawiona dla kolumna city wartość Gdańsk!
Jest to bardzo częsty błąd popełniany przez początkujących deweloperów. Dlatego też, komendę UPDATE
zawsze powinno się łączyć z klauzulą WHERE
, tak by zaktualizować tylko i wyłącznie interesujący nas rekord.
1
UPDATE address SET city = 'Gdańsk' WHERE id = 1;
Usuwanie danych
DELETE
Do skasowania danego rekordu z tabeli należy użyć komendy DELETE
. UWAGA! Tak jak w przypadku klauzuli UPDATE
, nie dodanie do zapytania klauzuli WHERE
spowoduje że dotknięte naszą operacją zostaną wszystkie rekordy tabeli.
Prawidłowe zapytanie z komendą DELETE
powinno wyglądać następująco:
1
DELETE FROM address WHERE id = 1;
TRUNCATE
Z kolei, jeśli usunięcie wszystkich danych z tabeli jest przez nas zamierzoną operacją, to do usunięcia wszystkich rekordów powinniśmy użyć komedy TRUNCATE
1
TRUNCATE TABLE address;
Modyfikowanie struktur
ALTER TABLE
Komenda ALTER TABLE
wykorzystywana jest do dodawania, modyfikowania oraz usuwania kolumn w tabeli. Za jej pomocą możemy dodać lub usunąć również contrainty.
Przykład użycia:
1
2
ALTER TABLE students
ADD index_number varchar(10);
ALTER COLUMN
Klauzula ALTER COLUMN
wykorzystywana jest do modyfikowania typu danych kolumny wraz z komendą ALTER TABLE
.
Przykład:
1
2
ALTER TABLE students
ALTER COLUMN index_number INTEGER;
ADD CONSTRAINT
Aby dodać constrainty do wcześniej stworzonej tabeli, należy wykorzystać klauzulę ADD CONSTRAINT
wraz z komendą ALTER TABLE
lub też podczas tworzenia tabeli (komenda CREATE TABLE
).
Przykład dodania klucza obcego tabeli adres dla tabeli student. Ważne! jeśli ważne jest również dodanie kolumny do tabeli, która będzie przechowywała klucz obcy.
1
2
3
4
5
6
ALTER TABLE students
ADD COLUMN address_id INT NOT NULL;
ALTER TABLE students
ADD CONSTRAINT id_address_fk
FOREIGN KEY (address_id) REFERENCES address(id);
Dodatkowo, podczas dodawania constrainów, możemy zdefiniować zachowanie się rekordów na akcje aktualizacji bądź usunięcia danych. Mowa o tzw nadaniach akcji:
ON UPDATE NO ACTION
orazON DELETE NO ACTION
- domyślny contraint dla aktualizacji oraz usuwania danych. Jeśli constraint zostanie złamany, wywołany zostanie błąd jeśli istnieją jakiekolwiek referencyjne wierszeON UPDATE RESTRICT
orazON DELETE RESTRICT
- działanie identyczne jak wNO ACTION
z tą różnicą że błąd zostanie wywołany odrazu, a nie np. podczas końca tranzakcjiON UPDATE CASCADE
orazON DELETE CASCADE
- aktualizacja lub usunięcie odbędzie się kaskadowo. To znaczy że dana akcja dotknie również referencyjne wierszeON DELETE SET NULL
- akcja dostępna tylko dlaDELETE
. Podczas wykonywania operacji usunięcia, ustawiany jestNULL
w wierszu, w którym posiadamy referencje do usuwanego wierszaON DELETE SET DEFAULT
- akcja dostępna tylko dlaDELETE
. Podczas wykonywania operacji usunięcia, ustawiana jest domyślna wartość (jeśli jest zdefiniowana) w wierszu, w którym posiadamy referencje do usuwanego wiersza
Akcje dla aktualizacji oraz usuwania można ze sobą łączyć. Przykład:
1
2
3
4
5
6
7
8
ALTER TABLE students
ADD COLUMN address_id INT NOT NULL;
ALTER TABLE students
ADD CONSTRAINT id_address_fk
FOREIGN KEY (address_id) REFERENCES address(id)
ON DELETE NO ACTION
ON UPDATE CASCADE;
Poniżej również przykład dodania nowej tabeli students
wraz z kluczem obcym do tabeli address
:
1
2
3
4
5
6
7
CREATE TABLE students(
id serial PRIMARY KEY,
index_number text,
address_id INT NOT NULL,
CONSTRAINT fk_address_id
FOREIGN KEY(address_id) REFERENCES address(id)
);
Usuwanie struktur
DROP
DROP
to podstawowa komenda do usuwania całych tabel.
Przykład usunięcia tabeli address:
1
DROP TABLE address;
Funkcje agregujące
AVG
Funkcja wyliczającą średnią dla danej kolumny numerycznej.
Przykład, zwracający średnią wartość roku urodzenia wszystkich studentów, którzy zaczeli studia w 2023 roku:
1
2
3
4
SELECT AVG(birth_year)
FROM students
WHERE start_of_studies = 2023;
SUM
Funkcja zwracająca sumę, dla danej kolumny numerycznej.
Przykład, zwracający całkowitą sumę czesnego zapłaconego przez studenta o indeksie s13784:
1
2
SELECT SUM(fee) FROM tuition_fees
WHERE student_index = 's13784';
MIN
Funkcja zwracająca minimalna wartość kolumny numerycznej bądź datowej.
Przykład, zwracający minimalną wartość zapłaconego czesnego przez studenta o indeksie s13784:
1
2
SELECT MIN(fee) FROM tuition_fees
WHERE student_index = 's13784';
MAX
Funkcja zwracająca maksymalną wartość kolumny numerycznej bądź datowej.
Przykład, zwracający maksymalną wartość zapłaconego czesnego przez studenta o indeksie s13784:
1
2
SELECT MAX(fee) FROM tuition_fees
WHERE student_index = 's13784';
COUNT
Funkcja zwracająca liczbę wierszy spełniającą dany warunek.
Przykład, zwracający liczbę wierszy (a zarazem też studentów), którzy zaczęli studia w 2023 roku:
1
2
SELECT COUNT(*) FROM students
WHERE start_of_studies = 2023;
Zadania
Pamiętaj by zapisać wykonane skrypty w swoim repozytorium. Na potrzeby dzisiejszych zajęć do folderu migrations
dodaj i pracuj na pliku V2__lab05.sql
. Kontynuujemy pracę nad bazą danych z poprzedniego laboratorium.
- Wykorzystując opisane wyżej klauzule, dodaj do tabel brakujące klucze obce, gdzie:
- Musisz wyczyścić wszystkie dane z co najmniej jednej tabeli (ale nie ze wszystkich tabel, zostaw przynajmniej po jednej tabeli, które mają ze sobą relacje)
- Musisz co najmniej raz usunąć jedną tabelę i stworzyć ją od nowa z kluczem obcym
- Musisz co najmniej raz zmodyfikować tabele i dodać do niej klucz obcy
- W pozostałych nie wyczyszczonych tabelach, zmodyfikuj dane przypisując do nich klucz obcy, którego wartość jest z tabeli z którą aktualizowana tabela ma relacje
- Dodaj do każdej tabeli przynajmniej 50 rekordów. Wykorzystaj przy tym narzędzie do mockowania danych np. Mockaroo