SQL · wiersze i kolumny zostały wyświetlone, ... Wypisz imiona i nazwiska uczniów nie...

27
1 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

Transcript of SQL · wiersze i kolumny zostały wyświetlone, ... Wypisz imiona i nazwiska uczniów nie...

1

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

2

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

3

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

4

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.

5

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ć,

6

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.

7

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-8-

1# 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;

8

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

9

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*’';

10

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 1-

10, 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');

11

10. Operatory logiczne dla programistów:

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.

12

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.

13

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;

14

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

15

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)

16

BETWEEN DAYOFMONTH(CURDATE()) AND 31 OR MONTH(Data_urodzenia)=

MOD(MONTH(CURDATE()), 12) + 1 ORDER BY Data_urodzenia

17

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;

18

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ć.

19

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;

20

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;

21

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ć).

22

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;

23

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.

24

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;

25

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).

26

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 Miasto Data_urodzenia Telefon Płeć

Jan Łukomski 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.

27

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 SET pole1=nowawartość[,pole2=nowawartość,..]

WHERE warunek

Uzupełniamy w tabeli uczniowie nr telefonu o kierunkowy:

UPDATE Uczniowie SET Telefony=”(71)”& Uczniowie.Telefony WHERE

Uczniowie.Id_k=3