Dzisiaj ruszamy na blogu z nową serią wpisów gościnnych, które będą ukazywać się w kategorii “Porcja wiedzy”. Na pierwszy ogień idą bazy danych i SQL.
O co chodzi?
Co jakiś czas będą się ukazywać artykuły gościnne z różnych technologii. Znajdziecie w nich podstawowe informacje związane z danym zagadnieniem oraz linki, gdzie uczyć się dalej. Od kilki miesięcy chodził mi głowie pomysł zbudowania na blogu bazy wiedzy z różnych technologii, ale sama oczywiście nie jestem w stanie napisać artykułów na tyle tematów, bo się zwyczajnie nie znam na wszystkich zagadnieniach 😉 Jakiś czas temu ukazał się wpis Joanny Hulek o algorytmach i pomyślałam, że fajnie byłoby zrobić z tego coś cyklicznego. Dlatego postanowiłam zawołać posiłki! I tak oto powstały wpisy gościnne. Od dziś możecie się ich spodziewać regularnie. Ogromnie dziękuję Agnieszce, która jest autorką tekstu poniżej za podzielenie się swoją wiedzą. Jeśli nie wiecie, czym są bazy danych i jak się w ogóle do nich zabrać, przeczytajcie koniecznie. Nawet jeśli zajmujecie się inną technologią, dobrze jest znać podstawy zagadnień związanych z bazami danych. Oddaję głos Agnieszce 🙂
Wstęp
Każdy na pewno słyszał już pojęcie “baza danych”. Tak naprawdę bez tego ciężko byłoby zrobić jakąś większą aplikację. Ale co to właściwie jest ta baza, jak wygląda? Baza danych (a konkretnie: relacyjna baza danych) to zespół połączonych ze sobą logicznie tabel, przechowujących używane przez nas na codzień dane (imiona, nazwiska, numery telefonów, numery kont bankowych, dane adresowe, ale także obrazy, dźwięki i wiele więcej).
Dane w tych tabelach są przechowywane w pewnym logicznym porządku – na przykład adresy są w jednej tabeli, imię i nazwisko w drugiej, a dane dotyczące płatności w trzeciej. Zasady określające ten podział noszą nazwę normalizacji (więcej poczytacie o tym tutaj), i są to dobre praktyki stosowane przy projektowaniu tabel. Tabele łączą się między sobą za pomocą tak zwanych kluczy – są to specjalne pola służące jednoznacznej identyfikacji danego rekordu, czyli wiersza danych. Te połączenia zwane są właśnie relacjami.
Dla przykładu, załóżmy że w tabeli z danymi osobowymi mamy pana Adama Kowalskiego, który ma przypisane ID o numerze 156. To ID będzie właśnie tym kluczem, który umożliwia nam odnalezienie powiązanych z panem Adamem danych w innych tabelach – odwołując się do tabeli z adresami, podajemy jego ID i otrzymujemy adres (lub adresy) przypisane do danej osoby. A jak właściwie wyciągać dane z bazy? Służy do tego specjalny język, którego trzon jest wspólny dla wszystkich relacyjnych baz danych.
Język SQL – jak działa?
Jeśli znacie już jakiś język programowania, to wiecie jak to jest – piszecie kolejne kroki, które komputer musi wykonać, byście uzyskali zamierzony efekt. Można powiedzieć, że te instrukcje są czymś w rodzaju serii rozkazów.
Język SQL natomiast (Structured Query Language, strukturalny język zapytań) działa na trochę innej zasadzie – mówimy, co chcemy uzyskać, a jak to ma zostać wykonane, to już nie nasz problem – tym się zajmuje silnik bazodanowy. Porównajmy sobie schemat działania “normalnego” języka programowania i języka SQL.
Przykład w pseudokodzie – chcemy wyciągnąć z szuflady z kuchni czerwony nóż:
idź do kuchni
otwórz drugą szufladę po lewej stronie
chwyć czerwony nóż
wyjmij czerwony nóż
zamknij szufladę
I teraz to samo, tylko w logice języka SQL:
Przynieś mi nóż z kuchni, jest w drugiej szufladzie po lewej stronie.
Ogólnie rzecz ujmując, tak to właśnie wygląda 😉 Omówmy sobie teraz pokrótce z czego składają się zapytania (zwane też kwerendami, od query).
Elementy języka zapytań
Podstawowym szkieletem zapytania będzie forma:
SELECT [lista pól z tabeli - co chcemy mieć w wyniku]
FROM [nazwa tabeli - skąd chcemy to mieć]
WHERE [dodatkowe warunki, filtry - jakie chcemy to mieć]
Wracając do przykładu z nożem, wyglądałoby to tak:
SELECT nóż
FROM druga_szuflada_po_lewej
WHERE kolor = 'czerwony'
W klauzuli WHERE warunków może być więcej, powiązanych ze sobą operatorami AND i OR – tak samo jak w językach programowania; można też używać nawiasów, porównań większe/mniejsze/równe, tworząc bardziej złożone wyrażenia logiczne.
Przeanalizujmy sobie kilka zapytań, żeby zobaczyć, jak to wszystko działa.
Przykład 1 (SQL Server, baza testowa Northwind):
SELECT CustomerID, OrderID, EmployeeID
FROM dbo.Orders
WHERE CustomerID = 'SAVEA' AND EmployeeID IN(1, 3, 9)
W tym zapytaniu wybieramy trzy kolumny z tabeli Orders, gdzie CustomerID jest równe ‘SAVEA’ oraz EmployeeID mieści się w zbiorze liczb 1, 3 i 9 (czyli ID ma być równe 1 lub 3 lub 9). Taką samą konstrukcję (zmienna IN zbiór) znajdziemy np w Pythonie.
Przykład 2 (SQL Server, baza testowa Northwind):
SELECT OrderID, CustomerID, OrderDate
FROM dbo.Orders
WHERE OrderID BETWEEN 10755 AND 10847
Przykład podobny jak powyżej, ale warunek mamy określony przy pomocy słów kluczowych BETWEEN… AND… – myślę że łatwo się domyślić o co tu chodzi; to po prostu inny sposób zapisu “większe od 10755 i mniejsze od 10847”.
Przykład 3 (baza Oracle):
SELECT *
FROM Flota
WHERE id_auta not in (SELECT id_auta FROM Pracownicy WHERE id_auta is not null);
Gwiazdka zaraz po SELECT oznacza, że chcemy z danej tabeli wybrać wszystkie kolumny. W warunku WHERE widzimy… zapytanie w zapytaniu (zwane podzapytaniem, podkwerendą, ang. subquery). Chodzi nam o to, że potrzebujemy id_auta, które nie należą (not in) do pewnego zbioru. Zbiór ten określamy za pomocą drugiego, niejako zagnieżdżonego zapytania. Całość działa w ten sposób, że silnik najpierw wykonuje zapytanie wewnętrzne, a jego wynik podstawia do zapytania zewnętrznego i wykonuje je bazując na uzyskanych danych.
Łączenie tabel
A co, jeśli chcielibyśmy wyciągnąć dane z więcej niż jednej tabeli? Tak naprawdę, to rzadko korzysta się z zapytań do jednej tabeli… Zobaczmy więc, jak działają JOINy.
JOIN jest używany do łączenia dwóch lub więcej tabel, w celu uzyskania bardziej komplementarnych danych. Wygląda tak:
SELECT dane.imie, dane.nazwisko, adresy.ulica, adresy.miasto
FROM dane JOIN adresy ON dane.id = adresy.id
W klauzuli FROM mamy wytypowane dwie tabele – dane (z danymi osobowymi) oraz adresy (z adresami). Łączymy je za pomocą JOIN, dając warunek dane.id = adresy.id, czyli po prostu parujemy dane na podstawie ich ID. Dla pana Adama z ID = 156 zostanie “dobrany” adres z ID = 156.
Notacja z kropką nie powinna być Wam obca; w SQLu również się z niej korzysta, tak jak w powyższym przykladzie, by określić, o pole z której tabeli nam chodzi. Jeśli tabela jest tylko jedna, to nie ma problemu, ale jeśli jest ich więcej, to trzeba określać z której tabeli pochodzi. By ułatwić sobie życie, i nie pisać całej nazwy tabeli (przy dużych zapytaniach byłoby to uciążliwe) możemy skorzystać z aliasów, czyli skróconej nazwy, którą sami nadajemy na potrzeby danego zapytania. Aliasy deklarujemy w klauzuli FROM, pisząc nazwa_tabeli as alias. Przeróbmy powyższy przykład tak, aby korzystał z tego dobrodziejstwa:
SELECT d.imie, d.nazwisko, a.ulica, a.miasto
FROM dane as d JOIN adresy as a ON d.id = a.id
Tabeli dane nadaliśmy alias d, a tabeli adresy – a.
UPDATE & INSERT
Jak zaktualizować jakieś pole w tabeli? Do tego służy polecenie UPDATE. Ogólnie wygląda to tak:
UPDATE [nazwa tabeli w której dokonujemy zmiany]
SET [nazwa pola] = [nowa wartość]
WHERE [warunki]
Przykład:
UPDATE dane
SET imie = 'Jan'
WHERE ID = 157
UWAGA: jeśli przy update nie dodamy klauzuli where, zaktualizowanie zostaną wszystkie rekordy w całej tabeli. A przeważnie nie o to nam będzie chodzić 😉 Także warto uważać.
Dwa słowa o transakcjach
Jeśli już przy aktualizowaniu jesteśmy, warto powiedzieć kilka słów o transakcjach, czyli o commit i rollback. Commit jest potwierdzeniem dokonanej transakcji, natomiast rollback ją cofa.
Wyobraźcie sobie, że macie otwarty przed sobą notatnik. Zaczynacie coś w nim pisać. Czy ten tekst tam na pewno jest? Niby tak. Ale jeżeli teraz go zamkniecie bez zapisywania, to tekst zniknie. Czyli jakby go nigdy nie było. Gdybyście kliknęli “zapisz”, wtedy zmiany byłyby na stałe.
Z commitem i rollbackiem jest podobnie. Robiąc update, wprowadzacie zmianę, ale dopiero commit ją zapisuje, utrwala. Jeśli jednak uznacie, że coś jest nie tak, lepiej zrobić rollback i jeszcze raz wszystko sprawdzić (np jeśli zobaczycie, że zaktualizowało się kilka tysięcy wierszy zamiast oczekiwanych kilku). Po każdym update MUSI nastąpić commit bądź rollback – dlatego, że na czas aktualizacji rekordu jest on blokowany dla innych użytkowników, a jeśli aktualizujemy dużą liczbę rekordów, to bardzo łatwo zablokować pół bazy (piszę z własnego doświadczenia ;)).
Wstawianie nowych wierszy do istniejącej tabeli
Często będziemy musieli wstawić nowe dane do istniejącej już tabeli. To zadanie zrealizujemy za pomocą polecenia INSERT, którego ogólna postać wygląda tak:
INSERT INTO [nazwa_tabeli] (lista pól)
VALUES (lista wartości dla pól)
Przykład:
INSERT INTO dane (id, imie, nazwisko)
VALUES (158, 'Janina', 'Nowak')
Możemy również dane do wstawienia wyciągnąć z innej tabeli. Robimy to tak:
INSERT INTO nowa_tabela (id, imie, nazwisko)
SELECT (old_id, old_imie, old_nazwisko)
FROM stara_tabela
WHERE id > 150
Podsumowanie & co dalej?
Mamy za sobą krótki wstęp do baz danych – wiemy mniej więcej, jak wyglądają i jak się z nich korzysta. Temat samych baz, jak i języków do ich obsługi, jest bardzo szeroki. Myślę jednak że warto wiedzieć – chociaż ogólnie – jak to wszystko działa, bo tak naprawdę korzystamy z nich codziennie… tyle, że w większości przypadków nieświadomie 😉
Czego właściwie potrzebujemy, gdybyśmy chcieli sami spróbować swoich sił przy bazach?
Każdy może sobie taką bazę zainstalować w domu. Jest to całkiem proste i darmowe, czemu więc nie spróbować?
Będziemy potrzebować dwóch elementów: silnika bazodanowego oraz programu do obsługi bazy, w którym będziemy pisać nasze zapytania, przeglądać strukturę tabel i robić inne fajne rzeczy.
Dla baz Microsoftu ściągamy sobie SQL Server w wersji Express, który będzie naszym silnikiem, i do tego Management Studio (bazodanowy odpowiednik Visual Studio).
Dla Oracle, będzie to Oracle Database Enterprise Edition, oraz na przykład SQL Developer.
Dodatkowo, dla każdej z tych baz, możemy sobie dołożyć małe, testowe bazy wypełnione danymi, by było na czym ćwiczyć.
Do niektórych systemów bazodanowych – na przykład Oracle i Microsoft SQL Server – dostajemy rozszerzenie języka SQL, które umożliwia dodawanie logiki do tabel. Te języki mają już więcej wspólnego z tradycyjnymi językami programowania, zawierają bowiem instrukcje warunkowe, pętle czy zmienne.
Dla Oracle mamy PL/SQL, a dla SQL Server jest T-SQL. Dzięki nim możemy na przykład oprogramować sprawdzanie poprawności danych przed zapisaniem ich w bazie – ot chociażby weryfikacja numerów PESEL (bo po co mamy trzymać nieprawidłowe?), albo wyciągnąć z bazy pewien zestaw danych i przetwarzać je rekord po rekordzie. Znając SQL i PL/SQL lub T-SQL możemy zostać programistą baz danych i robić właśnie tego typu rzeczy.
Przydatne linki:
Learn SQL – kurs na codecademy
sqlpedia – kurs MS SQL
O oracle ludzkim głosem – kurs Oracle SQL
sql-exercises – zbiór zadań z SQL wraz z rozwiązaniami
O autorce
Agnieszka Włodarczyk – z wykształcenia inżynier informatyk z zamiłowaniem do programowania, z zawodu… jeszcze-nie-programista 😉 W tej chwili zajmuje się utrzymaniem aplikacji w dużej korporacji. Więcej tekstów Agnieszki możecie przeczytać na jej blogu – Granice kodu.
I jak się podobało? Macie jakieś pytania? Piszcie śmiało pod tym postem!
Dzięki za ten wpis!
Dla mnie bomba proszę o wiecej? jak tworzyć raporty , jak sprawdzać poprawność danych w bazie itp
Ciekawy blog, gratulacje. Proponuję, abyś napisała coś więcej o złączeniach tabel i relacjach wiele-do-wielu bo wiem z doświadczenia, że sporo osób ma z tym problemy a jest to coś, bez czego chyba nie zrobi się dziś większej bazy relacyjnej (a przynajmniej w takim standardowym podejściu). Od siebie dodam, że do wymiany rozwiązań i ich analizy fajne jest sqlfiddle, działa analogicznie do jsfiddle czy codepen i znacznie ułatwia wzajemne pomaganie bo nie trzeba tracić czasu na tworzenie całej bazy aby przetestować jedno zapytanie 🙂
Pozdrawiam!
Dziękuję!
Tylko zaznaczę, że tekst jest autorstwa Agnieszki, ja tylko użyczyłam na niego miejsca na blogu 😉 I dziękuję za miłe słowa! 🙂
To tylko ma być taki wstęp, po resztę wiedzy trzeba ruszyć samemu 😀
Cieszę się, że się podoba. Podziękowania należą się przede wszystkim Agnieszce, bo naprawdę napisała super tekst 🙂
Fajnie ze tu są i bazy danych. Wiedza niezwykle przydatna w sumie w każdym aspekcie it. zapraszam również na mojego bloga, gdzie można poczytać o bazach trochę z innej perspektywy :
http://wynalazkowo.com/category/bazy-danych/
Wpis bardzo mi się podoba – otworzył oczy na wiele braków wiedzowych, dziękuję.
Asiu, super wpis 🙂
Fajnie, że pokazujesz, że jest więcej niż jeden system bazy danych.
Dzięki za miłe słowa! Chcę tylko zaznaczyć, że ja nie jestem autorką tego wpisu. Napisała go w ramach gościnnej serii postów Agnieszka Włodarczyk 🙂
Super! Ogromnie się cieszę, że wpis się przydał 🙂