SQL

Transkrypt

SQL
SQL
1. Wprowadzenie
SQL jest językiem uniwersalnym, "zrozumiałym" przez wszystkie systemy RDBMS
(Relational Data Base Management System)
SQL nie jest językiem programowania, jest językiem zapytań
Nie ma w nim instrukcji if, while czy for, ani zmiennych,. To nie jest 'programming
language' ale 'query language' czyli język zapytań. Mówi się często, że jest to język
deklaratywny. Chcemy pobrać z tabel dane, spełniające pewne kryteria i deklarujemy je za
pomocą zdania SQL
d fizycznej reprezentacji tabel.
nieinformatycy
deklaracji
podstawowych – wszystkie instrukcje SQL - SELECT, INSERT, DELETE, UPDATE,
CREATE - działają w swoich podstawowych opcjach tak samo
1
2. Historia języka SQL
Koncepcja RDBMS zrodziła się w IBM w San Jose (Kalifornia) w 1970 r. W tym samym
roku w "Communications of CACM" pojawił się artykuł opisujący koncepcję relacyjnej
bazy danych napisany przez jej autora, E.F. Codda.
Edgar Frank Codd (dzięki uprzejmości IBM
Pierwsza wersja systemu RDBMS została wdrożona w 1974, a w jej ramach
zaimplementowano prototypową wersję język Structured English Query Language (w
skrócie SEQUEL). Później usunięto z tej nazwy "English" i tak powstał SQL. Stał się on
standardowym językiem relacyjnych baz danych. Pierwszy komercyjny system RDBMS, z
językiem SQL, powstał w 1979 i został nazwany ORACLE.
Wysiłki organizacji ANSI i ISO doprowadziły do stworzenia w 1986 pierwszego standardu
SQL, zwanego SQL1 lub SQL-86
Plany na przyszłość:
m języka XML
lem programowania obiektowego
2
3. SELECT
W języku polskim zapytanie do bazy danych nazywa się kwerendą
Zdanie SELECT języka SQL jest złożone, ma wiele opcji i może ciągnąć się przez kilka
linii. Będziemy podawać w zdaniu SELECT dwie podstawowe informacje:
a) co pobrać, np. zawartość jakich kolumn (SELECT) i
b) skąd, tj. z jakiej tabeli lub tabel (FROM).
SELECT (to, co wybieramy)... FROM (tabela lub tabele, z których
wybieramy)
Najpierw zadamy zapytanie o całą zawartość tabeli Pracownicy. Chcemy, by wszystkie
wiersze i kolumny zostały wyświetlone, bez żadnych ograniczeń
SELECT * FROM Pracownicy;
Gwiazdka jest specjalną wartością - oznacza 'wszystko' czyli Pracownicy; zawartość
wszystkich kolumn. Zdanie SQL zamyka średnik.
Słowa kluczowe SQL mogą być pisane zarówno małymi jak i wielkimi literami (można
używać 'select', 'SELECT' i 'SELect'
SELECT Imię FROM Pracownicy;
Pobranie samych imion i podobnie samych nazwisk:
SELECT Nazwisko FROM Pracownicy;
Teraz imiona i nazwiska (nazwy kolumn w kwerendzie muszą być rozdzielone
przecinkiem):
SELECT Imię, Nazwisko FROM Pracownicy;
Zadanie: Pobierz imiona, nazwiska i nazwy stanowisk
3
4. ORDER BY
Chcemy, by wyświetlane rekordy były uporządkowane, np. alfabetycznie. Zatem do
naszych zdań SELECT dodamy opcję określania porządku: ORDER BY
SELECT (co wybieramy)... FROM (z jakiej tabeli lub tabel)...ORDER BY
(jak ma być uporządkowane)...
Kwerenda wypisująca listę imion i nazwisk, uporządkowaną alfabetycznie wg nazwisk:
SELECT Imię, Nazwisko FROM Pracownicy ORDER BY Nazwisko;
Lista pracowników od najstarszego do najmłodszego stażem, wg rosnącej daty :
SELECT Imię, Nazwisko, Data zatrudnienia FROM Pracownicy ORDER BY Data
zatrudnienia;
W tabelach wynikowych tych kwerend kolejność wierszy jest rosnąca: nazwisk alfabetycznie, dat - od wcześniejszych do późniejszych. Jest to kolejność domyślna.
Możemy ją również zadeklarować wprost, używając w opcji ORDER BY słowa ASC (po
nazwie kolumny).
SELECT Imię, Nazwisko, Data zatrudnienia FROM Pracownicy ORDER BY Data
zatrudnienia ASC;
Jeśli chcemy mieć uporządkowanie malejące, musimy w opcji ORDER BY - po nazwie
kolumny - podać słowo DESC (od ang. descending - malejąco). Np.
SELECT Imię, Nazwisko FROM Pracownicy ORDER BY Nazwisko DESC;
Zamiast podawania nazwy kolumny, wg której chcemy uporządkować wynik kwerendy,
można też podać jej numer (liczony od 1). Np.
SELECT Imię, Nazwisko FROM Pracownicy ORDER BY 2 DESC ;
Zadanie: Podaj listę pracowników wg działów (uporządkowane alfabetycznie, rosnąco), a
potem nazwiska, ale w obrębie tego samego działu uporządkowane malejąco.
4
5. DISTINCT
W niektórych kolumnach wartości powtarzały się. Teraz wyświetlimy tylko rekordy
różniące się w danym polu. Chcemy np. mieć tylko listę działów. Musimy użyć słowa
kluczowego DISTINCT (ang. różne).
SELECT DISTINCT Miasto FROM Pracownicy ORDER BY Dział;
I lista wszystkich przełożonych:
SELECT DISTINCT Przełożony FROM Pracownicy ORDER BY Przełożony;
Zadanie: Wypisz listę imion, imiona nie mogą się powtarzać
Zadanie: Co wyświetli polecenie:
SELECT DISTINCT Imię, DISTINCT Miasto FROM Pracownicy;
Tak, zdanie jest błędne. Można tylko raz podać DISTINCT. Zastosowanie tej opcji do dwóch
różnych kolumn prowadziłoby co najmniej do trudności interpretacyjnych: np. co wybrać,
5
6. Warunek prosty WHERE
Możliwość wyboru rekordów
SELECT (to co wybieramy)... FROM (tabela lub tabele, z których
wybieramy)... WHERE (kryteria wyboru)... ORDER BY (uporządkowanie
wyniku)
SELECT Imię, Nazwisko FROM Pracownicy WHERE Dział=#Sprzedaży#;
Po nazwie tabeli następuje WHERE i warunek określający, jakie rekordy mają zostać
wybrane. Ma on tu postać nazwa pola = wartość (oprócz znaku równości można używać
także innych operatorów
SELECT Imię, Nazwisko, Data zatrudnienia FROM Pracownicy WHERE
Przełozony=#Barcisz# ORDER BY Data zatrudnienia;
W opcji WHERE można nie tylko sprawdzać czy zawartość pola jest równa pewnej
wartości, ale także podawać inne warunki:
 czy jest od tej wartości większa (operator '>')
 mniejsza ('<')
 większa lub równa ('>=')
 mniejsza lub równa i('<=')
 nierówna ('<>')
Można te operatory stosować do różnych pól, także do dat. Oto kwerenda listująca imiona,
nazwiska i daty zatrudnienia przed 1 lutego 1983 r.:
SELECT Imię, Nazwisko, Data zatrudnienia FROM Pracownicy WHERE Data
zatrudnienia < #1/2/1983#;
Zadanie: Napisz kwerendę wyświetlającą pełne rekordy wszystkich Izabel i tylko ich.
6
7. Składanie warunków
Wybrane operatory opcji WHERE
Zadania: Tabela Uczniowie zawiera następujące pola: Imię, Nazwisko, Miasto, Data_urodzenia,
Płeć
Napisz zdanie SELECT wybierające wszystkie Anny z Warszawy (wypisz imiona i nazwiska).
Wiedząc, że wszyscy uczniowie są urodzeni w 1987 r., napisz zdanie SELECT wybierające
wszystkie uczennice z Gdyni urodzone w sierpniu.
Znajdź imię, datę urodzenia i telefon najmłodszej Krakowianki.
SELECT Imię, Nazwisko FROM Uczniowie WHERE Miasto='Gdynia' AND Płeć='K' AND Data_urodzenia >= #1987-81# AND Data_urodzenia <= #1987-8-31#;
SELECT Imię, Nazwisko FROM Uczniowie WHERE Imię ='Anna';
WHERE Miasto ='Kraków' AND Płeć='K' ORDER BY Data_urodzenia;
Warunek definiowany w opcji WHERE może być bardziej złożony. Oto kwerenda
wybierająca wszystkie uczennice z Krakowa:
SELECT Imię, Nazwisko FROM Uczniowie WHERE Płeć='K' AND Miasto='Kraków'
ORDER BY Nazwisko;
Zamiast AND jest OR (szukamy wszystkich pań z całej Polski, a także mieszkańców
Krakowa dowolnej płci):
SELECT Imię, Nazwisko FROM Uczniowie WHERE Płeć='K' OR Miasto='Kraków'
ORDER BY Nazwisko;
7
Operator
Opis
Operatory porównania
=
Równe
<>
Nierówne
>
Większy niż
<
Mniejszy niż
>=
Większy niż lub równy
<=
Mniejszy niż lub równy
Operatory logiczne
AND
Koniunkcja
OR
Alternatywa
NOT
Zaprzeczenie
Operatory ciągów znaków
LIKE
Maska na ciąg znaków
Operatory wyboru wartości
IN
Lista wartości.
BETWEEN
Zakres wartości
8
8. OPERATOR LIKE
Operator LIKE pozwala definiować kryterium wyboru rekordów, z określeniem ciągu
znaków, jakie dane pole ma zawierać, i miejsca tego ciągu w polu.
Załóżmy, że chcemy mieć listę uczniów pochodzących z miast, których nazwa rozpoczyna
się na literę K (Kraków, Konin, Katowice itd).
SELECT Imię, Nazwisko, Miasto FROM Uczniowie WHERE Miasto LIKE ’'K*’'
ORDER BY Nazwisko;
Zapis ‘'K*’' oznacza, że pierwszą literą w szukanym ciągu znaków ma być 'K', a reszta
(oznacza ją *) może być dowolna.
Aby znaleźć wszystkie miasta, których nazwy rozpoczynają się na P, trzeba w powyższej
kwerendzie podać '’P*’'. Jeśli chcielibyśmy znaleźć wszystkie miasta o nazwach
rozpoczynających się na ‘Ko’, trzeba by podać 'Ko*'.
Oto kwerenda wyszukująca wszystkie uczennice i uczniów, których nazwiska kończą się na
'ski' lub 'ska':
SELECT Imię, Nazwisko FROM Uczniowie WHERE Nazwisko LIKE '’*ski’' OR Nazwisko
LIKE '’*ska’' ORDER BY Nazwisko;
Zadania:
Wypisz wszystkie nazwiska uczniów zawierające literę u.
Wypisz imiona i nazwiska uczniów nie mieszkających w miastach, których nazwy
zaczynają się na literę W.
SELECT imię, nazwisko, Miasto FROM uczniowie WHERE Miasto NOT LIKE '’W*’';
SELECT Imię, Nazwisko FROM Uczniowie WHERE Nazwisko LIKE '’*u*’';
9
9. In oraz Beetween
Za pomocą IN określa się konkretne wartości w polu, jakie nas interesują (wartości te
podaje się w nawiasach, rozdzielając je przecinkami). Innymi słowy: tylko rekord mający w
danej kolumnie jedną z wartości podanych w IN będzie spełniać kryterium. Oto kwerenda
wyszukująca wszystkich uczniów mieszkających w Trójmieście:
SELECT Imię, Nazwisko, Miasto FROM Uczniowie WHERE Miasto IN ('Gdynia',
'Gdańsk', 'Sopot');
Wybrane zostaną tylko te rekordy, w których w polu Miasto znajduje się jedna z trzech
podanych nazw (rekordy z miastem "Kraków" czy "Warszawa" nie zostaną wybrane).
Można by podany warunek zapisać także jako
WHERE Miasto='Gdynia' OR Miasto='Gdańsk' OR Miasto='Sopot'
Operator BETWEEN pozwala określić zakres wartości pola od – do, jaki nas interesuje,
łącznie z wartościami granicznymi. Format wyrażenia z tym operatorem:
BETWEEN Wartość_1 AND Wartość_2.
Oto kwerenda wypisująca wszystkie dziewczęta z Krakowa, urodzone w styczniu 1987:
SELECT Imię, Nazwisko FROM Uczniowie WHERE Miasto='Kraków' AND Płeć='K'
AND Data_urodzenia BETWEEN #1987-1-1# AND #1987-1-31#;
Powyższy warunek na styczniową datę urodzin można też zapisać za pomocą WHERE
(WHERE Data_urodzenia >= #1987-1-1# AND Data_urodzenia <= #1987-1-31#).
Oto kwerenda wypisująca imię i nazwisko każdego ucznia, datę jego urodzenia i w
następnej kolumnie 1, jeśli data jest późniejsza niż 1 maja 1987 lub 0 w przeciwnym
wypadku.
SELECT Imię, Nazwisko, Data_urodzenia, Data_urodzenia >#'1987-5-1# FROM Uczniowie;
Uwaga: Z założenia zakres podany w BETWEEN jest 'w górę' - od wartości mniejszej do większej.
Zatem warunek BETWEEN 1 AND 10, podany w WHERE "działa" zawsze, ale BETWEEN 10 AND 1 nie musi. Są systemy RDBMS, w których jest obojętne czy zakres podawany w BETWEEN będzie 110, czy 10-1.
Zadania:
Rozwiąż problem z poprzedniej strony (dziewczęta z Krakowa i z Warszawy), bez użycia
operatora OR.
Podaj imiona, nazwiska i nazwy miast wszystkich uczniów nie pochodzących z trójmiasta.
SELECT Imię, Nazwisko, Miasto FROM Uczniowie WHERE Płeć='K' AND Miasto IN ('Kraków', 'Warszawa');
SELECT Imię, Nazwisko, Miasto FROM Uczniowie WHERE Miasto NOT IN ('Gdynia', 'Gdańsk', 'Sopot');
10
Operatory logiczne dla programistów:
10.
W MySQL operatory logiczne AND, OR i NOT można zapisywać także jako odpowiednio &&, || i !
Zadanie (dość trudne): Napisz kwerendę listującą imiona i nazwiska wszystkich uczennic oraz ich
atrakcyjność liczoną tak oto:
a) jeśli uczennica jest urodzona nie później niż 31 maja 1987 r., to jej atrakcyjność (tak ma się
nazywać kolumna) jest równa 1 (w przeciwnym razie - 0),
b) jeśli dziewczyna mieszka w Warszawie, jej atrakcyjność jest także 1 (dla innych miast - 0).
Atrakcyjności się sumują - jeśli obydwa przypadki są spełnione (czas urodzenia i miejsce
zamieszkania), to atrakcyjność łączna jest równa 2. W kolumnie atrakcyjności może być zatem
jedna z trzech wartości: 0, 1 lub 2.
SELECT Imię, Nazwisko, (Data_urodzenia <#1987-6-1#) + (Miasto = 'Warszawa') AS Atrakcyjność
FROM Uczniowie WHERE Płeć = 'K' ORDER BY Nazwisko;
Zadanie: Jaki będzie wynik następującej kwerendy?: SELECT "Uczniowie" FROM Uczniowie;
Zostanie zasygnalizowany błąd wykonania.
Nie. Kwerenda wykona się poprawnie. To, że w ciągu znaków w SELECT podano nazwę tabeli, występującej w opcji
FROM, jest całkowicie nieistotne - z punktu widzenia SQL jest to stały ciąg znaków (byłby błąd, gdyby pominięto
cudzysłowy) .
Wypisana zostanie pusta tabela, niezawierająca ani jednego wiersza.
Nie.
Wypisany zostanie tylko jeden wiersz z tekstem "Uczniowie".
Nie.
Wypisana zostanie liczba rekordów w tabeli Uczniowie.
Nie. Pomijając to, że obliczania liczby rekordów w tabeli jeszcze nie "braliśmy", nie ma tu nic co by sugerowalo to.
Wypisany zostanie wiersz "Uczniowie" tyle razy, ile jest rekordów w tabeli Uczniowie.
Tak. Ponieważ nie podano żadnego kryterium wyboru, z tabeli Uczniowie pobrane zostaną wszystkie rekordy. Dla
każdego zostanie wypisana ta sama stała wartość - ciąg znaków "Uczniowie" (nie interesuje nas żadne pole w
rekordzie, ani Imię ani Nazwisko). Jeśli masz watpliwości, możesz tę kwerendę wstawić do któregokolwiek pola
edycyjnego kursu, chociażby na poprzedniej stronie i wysłać do serwera.
11
Funkcje wbudowane
Funkcję wywołuje się, podając jej nazwę i w nawiasach (nie oddzielonych spacją od nazwy
funkcji) - argument lub argumenty funkcji, oddzielone przecinkami (istnieją funkcje
bezargumentowe). Argumentami funkcji są najczęściej pola w rekordzie (faktycznie nazwy
kolumn w tabeli).
Funkcje wbudowane SQL są różne. Najbardziej popularne to tzw. funkcje agregujące.
Bardzo często chcemy dokonać na bazie jakichś zapytań zbiorczych: obliczyć ile mamy
rekordów spełniających pewien warunek, znaleźć minimalną, maksymalną lub średnią
wartość w pewnej kolumnie (np. pensję pracowników) etc. Język SQL dostarcza
użytkownikowi funkcji, które można wykorzystać w takich zapytaniach. Najbardziej znane
z nich to funkcje standardowe: COUNT, SUM, AVG, MIN i MAX.
12
11.
Funkcja COUNT
Funkcja COUNT może być używana w dwojaki sposób. Pierwszym i najbardziej
popularnym jest liczenie rekordów spełniających dane kryteria COUNT(*)
Oto kwerenda podająca liczbę wszystkich rekordów w tabeli Uczniowie:
SELECT COUNT(*) FROM Uczniowie;
I liczba wszystkich uczennic mieszkających w Warszawie:
SELECT COUNT(*) FROM Uczniowie WHERE Miasto='Warszawa' AND Płeć='K';
Pojawia się problem: tytułem w kolumnie wynikowej jest "COUNT(*)" - pod taką nazwą
bowiem występuje ta kolumna w zdaniu SELECT. RDBMS automatycznie przypisuje
generowanemu polu nazwę podaną w kwerendzie (faktycznie tekst definiujący kolumnę), tu
COUNT(*) właśnie. Nazwa COUNT(*) nie mówi oczywiście nic o tym, jakie rekordy są
liczone. Po to, żeby tę nazwę zmienić, użyjemy kolejnej opcji zdania SELECT - czyli
ALIAS. Pozwala ona określić nazwę kolumny, by np. nazywała się 'Warszawianki':
SELECT COUNT(*) AS Warszawianki FROM Uczniowie WHERE
Miasto='Warszawa' AND Płeć='K';
Nazwa podana w opcji ALIAS musi być ciągiem znaków nie rozdzielonym spacją.
Najczęściej do rozdzielenia (pozornego) słów używa się podkreślenia. Moglibyśmy zatem
zamiast 'Warszawianki' użyć nazwy 'Uczennice_z_Warszawy' (rozdzielenie słów
myślnikiem - 'Uczennice-z-Warszawy' - da błąd).
Jeśli jako argument funkcji COUNT poda się nazwę kolumny np. COUNT(Telefon) (to
drugi sposób wywoływania tej funkcji), podana zostanie liczba wszystkich rekordów, które
w tej kolumnie nie mają wartości NULL.
Dwie następne funkcje, MIN i MAX, zwracają odpowiednio wartość najmniejszą i
największą w danej kolumnie (ściślej: wyrażenia będącego ich argumentem). A skoro
operatory porównania > i < mogą się odnosić także do dat, zatem w sposób naturalny
można wobec dat stosować funkcje MIN i MAX (np. MIN(Data_urodzenia) znajdzie
najmniejszą (najwcześniejszą) datę wśród dat urodzin).
Zadania:
Znajdź datę urodzenia najmłodszej uczennicy.
Napisz kwerendę podającą liczbę różnych miast, z których pochodzą uczniowie (np. po to, by
można było mówić "nasi uczniowie pochodzą z N różnych miejscowości w Polsce").
SELECT MIN(Data_urodzenia) FROM Uczniowie WHERE Płeć='K';
SELECT COUNT(DISTINCT Miasto) AS Miasta_naszych_uczniów FROM Uczniowie;
13
AS jest opcjonalne:
Tworząc w kwerendzie alias kolumny nie trzeba pisać AS - można podać nazwę aliasu po
spacji. Dwa zapisy
SELECT COUNT(*) AS Obliczony_wynik FROM ...
SELECT COUNT(*) Obliczony_wynik FROM ...
są poprawne i dadzą ten sam wynik. Ponieważ AS jest opcjonalne, to jeśli zapomni się
przecinka na liście kolumn, kolumna oddzielona od poprzedniej spacją zostanie
potraktowana jako alias poprzedniej (nie będzie komunikatu o błędzie). By takich sytuacji
uniknąć, zaleca się pisanie zawsze explicite AS
14
12.
Funkcje daty
Zaczniemy od zadania z poprzedniego tematu: 'Napisz zdanie SELECT wybierające
wszystkie Krakowianki urodzone w maju'. Poprzednio, rozwiązując je, sprawdzaliśmy datę
urodzenia (czy jest w zakresie 1-31 maja 1987). Wymagało to względnie dużo pisania, a co
ważniejsze: ograniczało się tylko do dat z roku 1987. Teraz zapiszemy rzecz prościej i
bardziej uniwersalnie. Użyjemy funkcji MONTH. Jej argumentem jest data, a funkcja
zwraca numer miesiąca w tej dacie. Oto rozwiązanie:
SELECT Imię, Nazwisko FROM Uczniowie WHERE Miasto = 'Kraków' AND Płeć =
'K' AND MONTH(Data_urodzenia) = 5;
Chcemy wiedzieć, w jakich dniach tygodnia rodzili się uczniowie. Wykorzystamy do tego
inną funkcję wbudowaną, DAYNAME, zwracającą nazwę dnia tygodnia (w języku
angielskim) danej daty.
SELECT Nazwisko, DAYNAME(Data_urodzenia) AS Dzień_tygodnia FROM
Uczniowie;
Inne funkcje daty:
Funkcja DAYOFMONTH(Date), która dla danej daty zwraca numer dnia w miesiącu
bezargumentowa funkcja CURDATE() zwracająca bieżącą datę, np.:
DAYOFMONTH( '1987-10-17') - zwraca 17
YEAR(Data_urodzenia)=1987 wybierze urodzonych w roku 1987
CURDATE() = zwraca bieżącą datę.
Oto wypis bieżącej daty:
SELECT CURDATE() AS Data_dzisiejsza;
dwuragumentowa funkcja MOD - modulo (nie jest to funkcja daty). Wywołanie
MOD(12,9) zwraca 3
Zadania:
Szukamy (imiona, nazwiska, daty urodzenia) tylko tych uczniów, którzy urodzili
się w niedzielę.
Chcemy wiedzieć, którzy uczniowie mają urodziny w tym miesiącu lub w
miesiącu następnym.
SELECT Imię, Nazwisko, Data_urodzenia, DAYNAME(Data_Urodzenia) AS Dzień_urodzin
FROM Uczniowie
WHERE DAYNAME(Data_Urodzenia) LIKE ‘'Sun*’' ORDER BY 2;
SELECT Imię, Nazwisko, Data_urodzenia FROM uczniowie WHERE
MONTH(Data_urodzenia)=MONTH(CURDATE()) AND DAYOFMONTH(Data_urodzenia)
15
BETWEEN DAYOFMONTH(CURDATE()) AND 31 OR MONTH(Data_urodzenia)=
MOD(MONTH(CURDATE()), 12) + 1 ORDER BY Data_urodzenia
16
13.
LENGTH
Zwraca długość ciągu. Np. wywołanie LENGTH('Kraków') daje wartość 6.
Zadanie: wyświetl imiona i nazwiska w tabeli Uczniowie od nazwiska najdłuższego do
najkrótszego, z podaniem liczb liter w nazwisku (w obrębie tych samych długości nazwiska
mają być uporządkowane alfabetycznie).
SELECT Imię, Nazwisko, LENGTH(Nazwisko) FROM Uczniowie ORDER BY
LENGTH(Nazwisko), Nazwisko;
Dwie następne i bliźniacze funkcje, LOWER i UPPER, pozwalają manipulować
wielkością liter w tabeli wynikowej. Ich argumentami są zazwyczaj pola tekstowe. Oto
kwerenda, dająca listę nazwisk pisanych wielkimi literami:
SELECT Imię, UPPER(Nazwisko) AS Nazwisko from Uczniowie ORDER by
Nazwisko;
Zadanie: Napisz kwerendę wyświetlającą trzy wartości: najmniejszą, największą i średnią
długość nazwiska ucznia (do obliczenia tej ostatniej użyj funkcji AVG, która zwraca
wartość przeciętną z pól mających wartości różne od NULL).
SELECT MIN(LENGTH(Nazwisko)) AS Najkrótsze, MAX(LENGTH(Nazwisko)) AS
Najdłuższe, AVG(LENGTH(Nazwisko)) AS Przeciętne FROM Uczniowie;
17
14.
Concat
Chcemy mieć w jednej kolumnie imię i nazwisko ucznia. W dodatku nazwisko ma być
wielkimi literami np. 'Michał ZUBRZYCKI' (całość ma być uporządkowana wg nazwisk).
Musimy zatem połączyć w jakiś sposób imię z nazwiskiem. W MySQL istnieje funkcja
CONCAT(Ciąg1, Ciąg2, Ciąg3,…), zwracająca jeden ciąg powstały z połączenia
wszystkich argumentów (w innych systemach RDBMS operatorem konkatencacji ciągów
jest ||). Oto pierwsze rozwiązanie zadania:
SELECT CONCAT(Imię, UPPER(Nazwisko)) AS Uczeń FROM Uczniowie ORDER
BY Nazwisko;
Lecz nazwiska są wielkimi literami i uporządkowane poprawnie, ale są połączone z
imionami w jeden ciągły tekst. Muszą być rozdzielone.
Zadanie: zmodyfikuj powyższą kwerendę tak, żeby imię i nazwisko (to ostatnie pisane
wielkimi literami) były w jednej kolumnie, ale rozdzielone spacją.
UPPER(Nazwisko)) AS Uczeń FROM Uczniowie ORDER BY Nazwisko;
Oto wersja rozwiązania zadania z użyciem funkcji CONCAT_WS:
SELECT CONCAT_WS(' ', Imię, UPPER(Nazwisko)) AS Uczeń FROM Uczniowie
ORDER BY Nazwisko;
Różnica jest praktycznie kosmetyczna Zarówno CONCAT_WS, jak i CONCAT, są
funkcjami własnymi MySQL i w innych systemach RDBMS mogą być niedostępne lub
inaczej się nazywać.
18
15.Substring
SUBSTRING , pozwala wybierać podciąg z ciągu znaków
SUBSTRING(ciąg_znaków, pozycja, długość)
Zadanie: Napisz kwerendę wypisującą inicjały wszystkich uczniów, z kropkami (np. Jan
Kowalski powinien być wypisany jako "J.K."). Lista powinnna być uporządkowana
alfabetycznie, rosnąco.
SELECT CONCAT(SUBSTRING(Imię, 1,1), '.', SUBSTRING(Nazwisko,1,1), '.') AS
Inicjały FROM Uczniowie ORDER BY 1;
Dodatkowe kolumny w kwerendzie
W jednym z poprzednich tematów była mowa o 'wyrażeniach selekcji' i o wartości stałej
jako kolumnie w kwerendzie. Napisanie w SELECT jako wyrażenia selekcji tylko ciągu
'Witajcie, relacyjne bazy danych!' (bez opcji FROM i nazwy tabeli) dawało w wyniku
kolumnę o tym tytule i tej wartości (jeden wiersz). Celem zadania jest utworzenie tabeli do
wypełnienia przez nauczyciela (w praktyce będą one drukowane i te wydruki będą
wypełniane).
Zadania: Chcemy mieć wydruk, na którym byłyby w jednej kolumnie imiona i nazwiska
uczniów (wielkimi literami) i obok pusta kolumna, o nazwie 'Obecność', gdzie moglibyśmy
stawiać np. krzyżyk, jeśli uczeń jest obecny.
Podobny problem: chcemy mieć wydruk, na którym w pierwszej kolumnie byłyby imiona i
nazwiska uczniów (wielkimi literami), a obok pięć pustych kolumn o skrótowych nazwach
'Pon', 'Wto', 'Śro', 'Czw', 'Pią', w których można by zaznaczać nieobecność ucznia w danym
dniu tygodnia.
SELECT CONCAT(Imię, ' ', UPPER(Nazwisko)) AS Uczeń, ' ' AS Obecność FROM
uczniowie ORDER BY Nazwisko;
SELECT CONCAT(Imię, ' ', UPPER(Nazwisko)) AS Uczeń,
' ' AS Pon,
' ' AS Wto,
' ' AS Śro,
' ' AS Czw,
' ' AS Pią
FROM uczniowie ORDER BY Nazwisko;
19
Które zapytanie jest niepoprawne i dlaczego?
SELECT Imię, Imię, Nazwisko, Miasto FROM Uczniowie;
SELECT COUNT (*) FROM Uczniowie WHERE Miasto='Warszawa';
SELECT Imię, Nazwisko FROM Uczniowie ORDER BY Nazwisko WHERE Płeć='K';
SELECT * FROM Uczniowie WHERE Data_urodzenia => #1987-6-1#;
SELECT COUNT(DISTINCT MONTH(Data_urodzenia)) FROM Uczniowie;
SELECT SUM(LENGTH(Nazwisko) + LENGTH(Imię))) AS Wszystkie_litery FROM
Uczniowie;
20
16.
Group by
Chcemy znaleźć liczby uczniów z poszczególnych miast. Np. liczbę uczniów z Warszawy
SELECT COUNT(*) FROM Uczniowie WHERE Miasto='Warszawa';
Chcemy dokonać zbiorczych obliczeń dla różnych miast, tj. mieć listę miast i przy każdym liczbę mieszkających w nim uczniów. Do rozwiązania tego zadania trzeba użyć innej opcji
zdania SELECT - GROUP BY.
SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto ORDER BY 2 DESC;
Opcja GROUP BY ("grupuj wynik wg") pozwala użyć funkcji agregujących (SUM, AVG,
MAX, MIN, COUNT) nie do całej tabeli, ale do grup wierszy w tabeli wynikowej. Innymi
słowy: GROUP BY określa zakres działania funkcji np. COUNT - tu działa ona dla każdego
miasta niezależnie (podobnie jest dla innych funkcji agregujących). Bez opcji GROUP BY
funkcja COUNT, a także pozostałe funkcje agregujące, działają na całej tabeli (na
wszystkich wierszach). Dla każdej grupy, tu: dla każdego miasta, GROUP BY generuje
jeden wiersz.
Jeśli, oprócz funkcji agregującej, będzie się chciało wyszukać inne kolumny, ale nie użyje
się opcji GROUP BY, zostanie zasygnalizowany błąd. Tak będzie np. w przypadku
kwerendy: SELECT Miasto, COUNT(*) FROM Uczniowie;
Przy próbie jej wykonania wypisany zostanie komunikat o mieszaniu kolumn z funkcjami
agregującymi, niedopuszczalnym bez użycia GROUP BY. Nie bardzo wiadomo jak
należałoby wypisać (potraktować) wynik powyższej kwerendy bez grupowania wyników
(które miasto i jaką liczbę podać).
21
Zadania:
Wypisz listę miast, z liczbą uczennic z każdego miasta, uporządkowaną malejąco wg
liczby uczennic.
Wypisz dla każdego miasta: miasto, imię i nazwisko (w jednej kolumnie) oraz datę
urodzenia najmłodszej uczennicy. Nazwisko ma być wielkimi literami, a kolumny 2 i 3
mają nazywać się 'Najmłodsza_uczennica' i 'Data_urodzenia'.
Napisz kwerendę listującą numery miesięcy, z liczbami uczniów, którzy urodzili się w
tym miesiącu, uporządkowaną malejąco wg liczby uczniów, a w obrębie tej samej liczby
urodzeń - wg numerów miesięcy, rosnąco. Kolumny mają być zatytułowane 'Miesiąc' i
'Liczba_uczniów'.
SELECT Miasto, CONCAT(Imię, ' ' , UPPER(Nazwisko)) AS Najmłodsza_uczennica,
MIN(Data_urodzenia) AS Data_urodzenia
FROM Uczniowie WHERE Płeć='K' GROUP BY Miasto;
SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Płeć='K' GROUP BY Miasto ORDER
BY 2 DESC;
SELECT Miasto, CONCAT(Imię, ' ' , UPPER(Nazwisko)) AS Najmłodsza_uczennica,
MIN(Data_urodzenia) AS Data_urodzenia
FROM Uczniowie WHERE Płeć='K' GROUP BY Miasto;
SELECT MONTH(Data_urodzenia) AS Miesiąc, COUNT(*) AS Liczba_uczniów FROM
Uczniowie GROUP BY 1 ORDER BY 2 DESC, 1 ASC;
22
17.
Having
Poprzednie zadanie: wygenerować listę miast, z liczbą uczennic pochodzących z każdego.
SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Płeć='K' GROUP BY
Miasto ORDER BY 2 DESC;
Chcemy wybrać tylko te miasta, z których pochodzą co najmniej dwie uczennice
SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto HAVING
COUNT(*) >= 2 ORDER BY 2 DESC;
Gdyby chodziło o miasta, z których pochodzi tylko jeden uczeń, warunek w HAVING
byłby COUNT(*)=1.
Podstawowa różnica między WHERE i HAVING polega na tym, kiedy w procesie
tworzenia tabeli wynikowej opcje te są wykorzystywane. Otóż WHERE służy do
określenia, które wiersze z tabeli wybrać, HAVING zaś 'działa' na rezultacie wyboru (już po
zastosowaniu WHERE). Tę różnicę widać w kwerendach.
Kwerenda
SELECT COUNT(*) FROM Uczniowie WHERE Miasto LIKE 'W%';
wykona się poprawnie (liczba uczniów mieszkających w miastach o nazwach
zaczynających się na literę W – WHERE wyszuka takie rekordy w tabeli Uczniowie).
Natomiast dwie kwerendy:
SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Miasto LIKE 'W%' GROUP BY
Miasto;
SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto HAVING Miasto
LIKE 'W%';
wykonają się identycznie.
23
18.
Limit
Pozwala kontrolować liczbę wierszy, jakie otrzymuje się w wyniku wykonania kwerendy.
Może mieć jeden albo dwa argumenty (liczby naturalne). Jeśli w LIMIT poda się tylko
jeden argument, SELECT potraktuje go jako liczbę wierszy, jakie ma wyświetlić. Oto
kwerenda wypisująca trzy pierwsze osoby z alfabetycznej listy uczniów:
SELECT * FROM Uczniowie ORDER BY Nazwisko LIMIT 3;
Jeśli w LIMIT poda się dwa argumenty (oddzielone przecinkiem), pierwszy z nich zostanie
potraktowany jako przesunięcie od początku wyniku (tyle pierwszych wierszy ma zostać
pominiętych), a drugi - jako liczba wierszy do wyświetlenia. Oto kwerenda wyświetlająca 7
wierszy z tabeli Uczniowie, począwszy od wiersza 5 (4 pierwsze mają być pominięte):
SELECT * FROM Uczniowie ORDER BY Nazwisko LIMIT 4, 7;
Zadania:
Napisz kwerendę, która wypisuje wszystkie wiersze z tabeli Uczniowie, począwszy od
15-tego (uporządkowanie wg nazwisk).
Wiedząc, że do wybierania losowo rekordów z tabeli można użyć bezargumentowej
funkcji RAND() (trzeba jej użyć w opcji ORDER BY), napisz kwerendę wybierającą trzy
przypadkowe osoby z tabeli Uczniowie (np. do odpytywania przez nauczyciela).
Napisz kwerendę wypisującą najdłuższe nazwisko ucznia, z długością tego nazwiska
(liczba znaków).
SELECT Imię, Nazwisko FROM Uczniowie ORDER BY RAND() LIMIT 3;
24
Podsumowując: lista, porządek i sens opcji zdania SELECTSELECT (to co
wybieramy)...
FROM (tabela lub tabele, z których wybieramy)
WHERE (kryteria wyboru)
GROUP BY(wg jakiej kolumny grupować)
HAVING (filtr na grupowaną zawartość)
ORDER BY (uporządkowanie wyniku)
LIMIT (ograniczenia liczby wybranych rekordów)
Zadanie: Wybierz niepoprawne zapytanie(wszystkie odnoszą się do tabeli Uczniowie)
SELECT Imię, Imię, Nazwisko, Miasto FROM Uczniowie;
OK - w zdaniu SELECT można wybierać więcej niż raz tę samą kolumnę.
SELECT COUNT (*) FROM Uczniowie WHERE Miasto='Warszawa';
BŁĄD - między COUNT a nawiasem otwierającym nie może być spacji.
SELECT Imię, Nazwisko FROM Uczniowie ORDER BY Nazwisko WHERE
Płeć='K';
BŁĄD - zła kolejność: najpierw powinno być kryterium określające rekordy
do wybrania (WHERE), a po nim podany sposób uporządkowania wyniku
(ORDER BY).
SELECT * FROM Uczniowie WHERE Data_urodzenia => '1987-6-1';
BŁĄD - źle napisany operator "większy lub równy"( powinno być >=).
SELECT COUNT(DISTINCT MONTH(Data_urodzenia)) FROM Uczniowie;
OK - zapytanie poprawne (kwerenda oblicza liczbę różnych miesięcy, w
których rodzili się uczniowie, maksymalnie 12).
SELECT SUM(LENGTH(Nazwisko) + LENGTH(Imię))) AS Wszystkie_litery
FROM Uczniowie;
Błąd - Wprawdzie kwerenda jest logicznie poprawna - obliczenie łącznej sumy
liter w imionach i nawiskach wszystkich uczniów - ale ma jeden nawias
zamykający za dużo (jak się go usunie, kwerenda zadziała).
25
Podstawową - i na razie jedyną - tabelą w naszej bazie danych będzie tabela Uczniowie.
Każdy uczeń będzie w niej opisany przez rekord o 6 polach:
 Imię
 Nazwisko
 Miasto - Zakładamy, że uczniowie mogą mieszkać w różnych miastach Polski
 Data_urodzenia - Data w formacie 2004-10-23 (dopuszczalny też będzie format z
ukośnikami jako separatorami, np. 2004/10/23).
 Telefon - ciąg znaków (nie zakładamy nic o formacie numeru
 Płeć - Pole może przybierać tylko dwie wartości: 'K' (kobieta) lub 'M' (Mężczyzna)
Imię Nazwisko
Jan
Łukomski
Miasto
Data_urodzenia Telefon Płeć
Warszawa 1990-12-10
826-44-56 M
Anna Wierzbicka Kraków
1987-2-21
621-66-10
K
...
...
...
...
...
...
Użyto tu polskich liter. Można ich oczywiście używać także w zdaniach SQL. O
typach pól (znakowe, numeryczne, data) będziemy mówić później, tu wystarczy,
gdy powiemy, że wszystkie pola w tabeli Uczniowie są znakowe, z wyjątkiem
daty - ta ma szczególny format, którym jest data właśnie i RDBMS to rozumie,
pozwalając nam pisać np. '1987-02-03', '1987-2-3', '1987/2/3' - wszystkie one
zostaną odczytane poprawnie i system będzie rozumiał, co w nich jest rokiem, co
miesiącem, co dniem (przyjmie też datę bez separatorów, w postaci '19870312',
ale ten format zapisu wymaga podawania zawsze dwóch cyfr miesiąca i dnia i jest
mało czytelny). Zrozumie również, jeśli podamy warunek data > '2004-1-1' (data
późniejsza niż 1 stycznia 2004 r.), ale nie przyjmie w dacie zbędnych spacji: data
'2004- 1 -1' zostanie uznana za błędną. Stosowany przez nas format daty jest
formatem ISO.
26
Wybieranie informacji z wielu tabel – polecenie JOIN
SELECT tabela1.pole1, tabela2.pole2 FROM tabela1 INNER JOIN tabela2 ON
tabela1.pole0=tabela2.pole3
Np. Tabela Klienci zawier pola Imiona, nazwiska, aNumery tabela Telefony. Tabele
połaczone są relacją jeden-do-wielu poprzez pole id_k. Chcemy uzyskac kwerende
zawierajaca imiona, nazwiska i numery telefonów.
SELEKT Klienci.Nazwisko, Klienci.Imię, Telefony.Numery FROM Klienci INNER JOIN
Telefony ON Klienci.Id_k=Telefony.Id_k
Chcemy aby imię i nazwisko były połączone w jednym polu:
SELEKT Klienci.Nazwisko,+ ‘ ‘ + Klienci.Imię AS Nazwanowegopola, Telefony.Numery
FROM Klienci INNER JOIN Telefony ON Klienci.Id_k=Telefony.Id_k
INSERT INTO
Wstawienie do tabeli nowego rekordu
INSERT INTO nazwa tabeli (pole1, pole2) VALUES (wrtość1, wartość2)
Do tabeli Uczniowie dodajemy nowy rekord:
INSERT INTO Uczniowie (Imię, Nazwisko, Miasto, Data_urodzenia,
Telefon) VALUES (‘Kazimierz’,’Kazimierzowy’,’Kraków’,’1988-02-03’)
UPDATE
Modyfikacja jednego lub wielu pól
UPDATE nazwatabeli
WHERE warunek
SET
pole1=nowawartość[,pole2=nowawartość,..]
Uzupełniamy w tabeli uczniowie nr telefonu o kierunkowy:
UPDATE Uczniowie SET Telefony=”(71)”& Uczniowie.Telefony WHERE
Uczniowie.Id_k=3
27

Podobne dokumenty