Wprowadzenie Funkcje tekstowe Funkcje liczbowe Funkcje daty i czasu Funkcje konwersji Funkcje serwera MySQL Na podstawie: webmaster.helion.pl oraz: ihelp.ovh.org Tak jak we wszystkich innych językach programowania, w języku SQL funkcje stanowią potężne narzędzie w pracy programisty zamiast samodzielnie pisać skomplikowane programy, wystarczy wywołać odpowiednią funkcję. W tym odcinku nauczysz się wywoływać funkcje systemowe i poznasz niektóre funkcje serwera MySQL. Wprowadzenie Wbudowane funkcje serwerów baz danych można podzielić na trzy kategorie: 1. Funkcje skalarne zwracają pojedynczą wartość obliczoną na podstawie zera lub większej liczby prostych argumentów. 2. Funkcje grupujące zwracają pojedynczą wartość dla zbioru argumentów wywołania. 3. Funkcje typu RowSet zwracające dane w postaci tabelarycznej, do których odwołujemy się tak jak do tabel. Na podstawie typu parametrów wywołania funkcje skalarne można podzielić na: 1. Funkcje tekstowe operujące na ciągach znaków. 2. Funkcje liczbowe operujące na liczbach. 3. Funkcje daty i czasu operujące na danych typu data i godzina. 4. Funkcje konwersji służące do zmiany typu danych. 5. Na specjalne wyróżnienie zasługują funkcje kryptologiczne, które pozwalają zaszyfrować, odszyfrować i podpisać wiadomość oraz sprawdzić jej autentyczność. W języku SQL funkcje można zagnieżdżać do dowolnego poziomu. Funkcje najbardziej wewnętrzne obliczane są w pierwszej kolejności, a na podstawie ich wyników obliczane są funkcje zewnętrzne. Funkcje tekstowe Argumentem funkcji tekstowych są ciągi znaków (dane typów char, varchar lub text). Typ danych zwracanych przez funkcje tekstowe jest podstawą do ich dalszego podziału: wyróżniamy funkcje tekstowe zwracające wartość znakową i funkcje tekstowe zwracające liczbę. 1
Funkcje tekstowe zwracające tekst CONCAT() Funkcja łączy (konkatenuje) przekazane jako parametr i oddzielone przecinkami ciągi znaków. Używaliśmy już tej funkcji, a w następnych listingach użyjemy jej jeszcze kilka razy. CONCAT_WS() Funkcja łączy (konkatenuje) przekazane jako parametr i oddzielone przecinkami ciągi znaków, rozdzielając je przekazanym jako pierwszy parametr ciągiem znaków. LOWER() Wynikiem działania funkcji LOWER() jest ciąg znaków podany jako argument, ale składający się wyłącznie z małych liter. Za pomocą tej funkcji wszystkie wielkie litery argumentu zostaną zamienione na małe. Aby na przykład wyświetlić nazwiska wszystkich współpracowników za pomocą małych liter, napiszemy (listing 12.1): Listing 12.1. Funkcji skalarnych można używać m.in. w klauzulach SELECT, WHERE i ORDER BY SELECT title, LOWER(title) FROM customer WHERE customer_id<3; +-------+--------------+ title lower(title) +-------+--------------+ Miss miss Mr mr +-------+--------------+ UPPER() Wynikiem działania funkcji UPPER() jest ciąg znaków podany jako argument, ale składający się wyłącznie z wielkich liter. Za pomocą tej funkcji wszystkie małe litery argumentu zostaną zamienione na wielkie. Aby na przykład uszeregować nazwy wszystkich towarów alfabetycznie według ich nazw, bez względu na wielkość użytych w nazwie liter, napiszemy (listing 12.2): Listing 12.2. Poszczególne klauzule instrukcji są od siebie niezależne dane mogą być na przykład sortowane według wyrażenia niewymienionego w klauzuli SELECT SELECT * FROM item ORDER BY UPPER(description); +---------+-----------------+------------+------------+ item_id description cost_price sell_price +---------+-----------------+------------+------------+ 10 Carrier Bag 0.01 0.00 7 Fan Large 13.36 19.95 2
6 Fan Small 9.23 15.75 3 Linux CD 1.99 2.49 5 Picture Frame 7.54 9.95 9 Roman Coin 2.34 2.45 2 Rubik Cube 7.45 11.49 11 Speakers 19.73 25.32 12 SQL Server 2005 NULL NULL 4 Tissues 2.11 3.99 8 Toothbrush 0.75 1.45 1 Wood Puzzle 15.23 21.95 +---------+-----------------+------------+------------+ LEFT() Za pomocą funkcji LEFT() z podanego jako argument ciągu znaków zostanie wycięta określona liczba znaków, począwszy od lewej strony. Aby odczytać inicjały klientów, wykonamy instrukcję pokazaną na listingu 12.3. Listing 12.3. Przykład zagnieżdżania funkcji najpierw odczytywane są pierwsza litera imienia i nazwiska, a następnie są one łączone w jeden ciąg SELECT CONCAT(LEFT(fname,1), LEFT(lname,1)) FROM customer; +--------------------------------------+ CONCAT(LEFT(fname,1), LEFT(lname,1)) +--------------------------------------+ JS AS AM AM SC NM RS AS CH MH DJ RN LH BN DH NULL +--------------------------------------+ RIGHT() Za pomocą funkcji RIGHT() z podanego jako argument ciągu znaków zostanie wycięta określona liczba znaków, począwszy od prawej strony (listing 12.4). 3
Listing 12.4. Wyświetlamy dane wyłącznie tych osób, których imiona kończą się na litery rd SELECT title, lname, fname FROM customer WHERE RIGHT(fname,2) = 'rd'; +-------+--------+---------+ title lname fname +-------+--------+---------+ Mr Stones Richard Mr Neill Richard +-------+--------+---------+ TRIM(), LTRIM() i RTRIM() Funkcja LTRIM() z podanego ciągu znaków usuwa wiodące spacje, funkcja RTIM() usuwa kończące (wolne) spacje, a funkcja TRIM() zarówno wiodące, jak i wolne spacje (listing 12.5). Listing 12.5. Przed zapisaniem danych do bazy z reguły warto usunąć z nich przypadkowo dodane spacje SELECT ltrim(' barba dos '; +---------------------------+ ltrim(' barba dos ') +---------------------------+ barba dos +---------------------------+ SELECT rtrim(' barba dos '); +---------------------------+ rtrim(' barba dos ') +---------------------------+ barba dos +---------------------------+ SELECT trim(' barba dos '); trim(' barba dos ') barba dos REPLACE() Za pomocą funkcji REPLACE() w ciągu znaków podanym jako pierwszy parametr zostanie wyszukany ciąg podany jako jej drugi parametr, a następnie w miejsce znalezionego ciągu będzie podstawiony ciąg podany jako trzeci parametr wywołania. Jeżeli trzeci parametr nie zostanie podany, z ciągu podstawowego będzie wycięty wyszukany ciąg znaków (listing 12.6). 4
Listing 12.6. Funkcja REPLACE jest niezastąpiona na przykład przy przygotowywaniu kolejnej wersji tego samego zestawienia SELECT REPLACE('Kierownik niech nam żyje', ' żyje', 'zgnije'); +---------------------------------------------------------+ REPLACE('Kierownik niech nam żyje', ' żyje', 'zgnije') +---------------------------------------------------------+ Kierownik niech nam zgnije +---------------------------------------------------------+ SUBSTRING() W wyniku działania funkcji SUBSTRING() zostanie zwrócona określona liczba znaków z łańcucha tekstowego, począwszy od podanej pozycji. Jeżeli nie podamy liczby zwracanych znaków, zwrócone będą wszystkie znaki występujące po pozycji określonej przez drugi parametr. Podanie ujemnej wartości drugiego parametru spowoduje, że znaki będą liczone od prawej do lewej (listing 12.7). Listing 12.7. Siedem liter, począwszy od piątej, z nazw produktów SELECT SUBSTRING(description,5,7) FROM item; +----------------------------+ SUBSTRING(description,5,7) +----------------------------+ Puzzle k Cube x CD ues ure Fra Small Large hbrush n Coin ier Bag kers Server +----------------------------+ SPACE() Działanie funkcji SPACE() powoduje zwrócenie liczby spacji określonej jako parametr (listing 12.8). Listing 12.8. Zamiast ręcznie dodawać spacje, możemy użyć do tego funkcji SPACE() SELECT CONCAT(fname, SPACE(3), lname) FROM customer; 5
+--------------------------------+ CONCAT(fname, SPACE(3), lname) +--------------------------------+ Jenny Stones Andrew Stones Alex Matthew Adrian Matthew Simon Cozens Neil Matthew Richard Stones Ann Stones Christine Hickman Mike Howard Dave Jones Richard Neill Laura Hendy Bill Neill David Hudson NULL +--------------------------------+ REVERSE() Funkcja REVERSE() zwraca ciąg znaków będący palindromem argumentu wywołania, czyli ciągiem znaków o odwróconej kolejności liter (listing 12.9). Listing 12.9. Zapytanie zwracające imiona będące palindromami SELECT fname from customer WHERE REVERSE(fname) = fname; +-------+ fname +-------+ Anna +-------+ Funkcje tekstowe zwracające liczby LENGTH() Funkcja LENGTH() jako wynik zwraca długość ciągu znaków podanego jako parametr jej wywołania. Jeżeli wywołamy funkcję LENGTH() z wartością Null, funkcja zwróci wartość Null. Za pomocą poniższej instrukcji wyświetlimy tylko te opisy towarów, które mają długie (dłuższe niż 10-znakowe) nazwy (listing 12.10). Listing 12.10. Funkcja LENGTH() użyta do selekcji wierszy SELECT description, LENGTH(description) 6
FROM item WHERE LENGTH(description)>10; +-----------------+---------------------+ description LENGTH(description) +-----------------+---------------------+ Wood Puzzle 11 Picture Frame 13 Carrier Bag 11 SQL Server 2005 15 +-----------------+---------------------+ INSTR() W wyniku działania funkcji INSTR() będzie zwrócona pozycja, na której w ciągu znaków podanym jako pierwszy parametr został znaleziony ciąg znaków podany jako drugi parametr. Jeżeli szukany ciąg znaków nie będzie znaleziony, funkcja zwróci 0 (listing 12.11). Listing 12.11. Wykorzystanie funkcji INSTR() do wybrania produktów, które w nazwie mają literę a SELECT description FROM item WHERE INSTR(description, 'a')>0; +---------------+ description +---------------+ Picture Frame Fan Small Fan Large Roman Coin Carrier Bag Speakers +---------------+ Funkcje liczbowe Funkcje liczbowe pozwalają wykonywać dodatkowe (oprócz dodawania, odejmowania czy mnożenia) operacje matematyczne oraz formatować liczby. ROUND() Działanie funkcji ROUND() polega na zaokrągleniu liczby do określonej liczby cyfr po przecinku. Pierwszy parametr jest liczbą do zaokrąglenia, drugi wskazuje, do ilu pozycji chcemy ją zaokrąglić. Ujemna wartość powoduje zaokrąglenie liczby z lewej strony przecinka; 0 spowoduje zaokrąglenie do najbliższej liczby całkowitej. Jeżeli drugi parametr nie jest podany, serwer baz danych przyjmuje domyślnie jego wartość jako równą 0 (listing 12.12). Listing 12.12. Przykład użycia funkcji ROUND() 7
SELECT Round(3.1415926535897,4); Round(3.1415926535897,4) 3.1416 SELECT Round(3.1415926535897,0); Round(3.1415926535897,0) 3 SELECT Round(3.1415926535897); +------------------------+ Round(3.1415926535897) +------------------------+ 3 +------------------------+ TRUNCATE() Funkcja TRUNCATE() powoduje obcięcie liczby do określonej liczby cyfr po przecinku. Pierwszy parametr jest liczbą do obcięcia, drugi wskazuje, do ilu pozycji chcemy liczbę skrócić. Ujemna wartość powoduje dodanie określonej liczby zer z lewej strony przecinka. Jeżeli drugi parametr nie jest podany, MySQL przyjmuje domyślnie jego wartość jako równą 0 (listing 12.13). Listing 12.13. Obcięcie miejsc po przecinku i zaokrąglenie do iluś miejsc po przecinku to dwie operacje SELECT Truncate(3.1415926535897,4); +-----------------------------+ Truncate(3.1415926535897,4) +-----------------------------+ 3.1415 +-----------------------------+ ABS() Wynikiem działania funkcji ABS() jest wartość bezwzględna liczby (liczba bez znaku). Jako parametr podaje się liczbę, której wartość bezwzględną należy obliczyć (listing 12.14). Listing 12.14. Funkcja ABS() użyta do sprawdzenia, czy dana liczba jest dodatnia SELECT * FROM item 8
WHERE sell_price!= ABS(sell_price); Empty set CEILING(), FLOOR() Za pomocą funkcji CEILING() zwrócona zostanie najmniejsza liczba całkowita równa liczbie podanej jako argument funkcji lub większa. Funkcja FLOOR() zwraca największą liczbę całkowitą równą liczbie podanej jako argument funkcji lub mniejszą (listing 12.15). Listing 12.15. Zwróć uwagę na wynik wywołania funkcji z argumentem Null SELECT sell_price, CEILING(sell_price), FLOOR(sell_price) FROM item; +------------+---------------------+-------------------+ sell_price CEILING(sell_price) FLOOR(sell_price) +------------+---------------------+-------------------+ 21.95 22 21 11.49 12 11 2.49 3 2 3.99 4 3 9.95 10 9 15.75 16 15 19.95 20 19 1.45 2 1 2.45 3 2 0.00 0 0 25.32 26 25 NULL NULL NULL +------------+---------------------+-------------------+ POWER(), POW() Funkcja POWER() sprawia, że liczba podana jako pierwszy parametr zostanie podniesiona do potęgi podanej jako drugi parametr. Wartości drugiego parametru mogą być mniejsze niż zero (listing 12.16). Listing 12.16. Często tę samą funkcję możemy wywołać za pomocą kilku nazw SELECT POWER(10,2), POW(2,10); +-------------+-----------+ POWER(10,2) POW(2,10) +-------------+-----------+ 100 1024 +-------------+-----------+ 9
SQRT() W wyniku działania funkcji SQRT() zwrócony będzie pierwiastek kwadratowy z liczby podanej jako parametr wywołania (listing 12.17). Listing 12.17. Przykład użycia funkcji SQRT() SELECT SQRT(10), SQRT(16); +--------------------+----------+ SQRT(10) SQRT(16) +--------------------+----------+ 3.1622776601683795 4 +--------------------+----------+ MOD() Funkcja MOD() zwraca jako wynik wartość reszty po podzieleniu liczby podanej jako pierwszy parametr przez dzielnik podany jako drugi parametr wywołania funkcji. Jeżeli wartość drugiego parametru wynosi 0, zwracana jest liczba podana jako pierwszy parametr (listing 12.18). Listing 12.18. Zapytanie zwracające dane towarów o parzystych identyfikatorach SELECT * FROM item WHERE MOD(item_id,2)=0; +---------+-----------------+------------+------------+ item_id description cost_price sell_price +---------+-----------------+------------+------------+ 2 Rubik Cube 7.45 11.49 4 Tissues 2.11 3.99 6 Fan Small 9.23 15.75 8 Toothbrush 0.75 1.45 10 Carrier Bag 0.01 0.00 12 SQL Server 2005 NULL NULL +---------+-----------------+------------+------------+ Funkcje trygonometryczne SIN(), COS(), TAN() i COT() W wyniku działania funkcji SIN() (sinus), COS() (cosinus), TAN() (tangens) i COT() (cotangens) zwrócona zostanie wartość odpowiednich funkcji trygonometrycznych dla parametru będącego kątem w radianach będzie obliczony odpowiednio: sinus, cosinus, tangens lub cotangens. Aby przeliczyć kąty z radianów na stopnie, należy posłużyć się wzorem: stopnie PI()/180 = radiany (listing 12.19). Listing 12.19. Przykład użycia funkcji trygonometrycznych SELECT SIN(200), COS(200), COT(200); 10
+-------------------+------------------+-------------------+ SIN(200) COS(200) COT(200) +-------------------+------------------+-------------------+ -0.87329729721399 0.48718767500701-0.55787150213477 +-------------------+------------------+-------------------+ RAND() Funkcja RAND() zwraca pseudolosową liczbę z przedziału od 0 do 1. Serwer MySQL oblicza tę wartość dla każdego wiersza wyniku (listing 12.20), co pozwala użyć funkcji RAND() do losowego wybierania danych z tabeli (listing 12.21). Listing 12.20. MySQL w przeciwieństwie do niektórych serwerów baz danych wylicza wartości funkcji RAND() dla każdego wiersza wyniku SELECT RAND(), description FROM item; +------------------+-----------------+ RAND() description +------------------+-----------------+ 0.93018501059169 Wood Puzzle 0.14203970892545 Rubik Cube 0.9196435435858 Linux CD 0.17209862188632 Tissues 0.10156250940781 Picture Frame 0.99151671211376 Fan Small 0.65289606307903 Fan Large 0.2899302097875 Toothbrush 0.49096289043404 Roman Coin 0.58502385354137 Carrier Bag 0.45223062713838 Speakers 0.50608160580143 SQL Server 2005 +------------------+-----------------+ Listing 12.21. Każde wywołanie tej instrukcji zwróci informację o innym, losowo wybranym towarze SELECT * FROM item ORDER BY RAND() LIMIT 1; +---------+-------------+------------+------------+ item_id description cost_price sell_price +---------+-------------+------------+------------+ 9 Roman Coin 2.34 2.45 +---------+-------------+------------+------------+ 11
SIGN() Funkcja SIGN() zwraca 1, jeżeli argumentem jej wywołania była liczba większa od 0, lub 0, jeżeli argumentem jej wywołania było 0, albo 1, jeżeli została wywołana dla liczby mniejszej od zera. W listingu 12.22 użyto jej do wyróżniania informacji o tym, czy cena sprzedaży towaru była wyższa od ceny jego zakupu. Listing 12.22. Funkcja SIGN() wywołana dla wyniku odjęcia wartości dwóch kolumn SELECT description,sign(sell_price-cost_price) FROM test.item; +-----------------+-----------------------------+ description SIGN(sell_price-cost_price) +-----------------+-----------------------------+ Wood Puzzle 1 Rubik Cube 1 Linux CD 1 Tissues 1 Picture Frame 1 Fan Small 1 Fan Large 1 Toothbrush 1 Roman Coin 1 Carrier Bag -1 Speakers 1 SQL Server 2005 NULL +-----------------+-----------------------------+ FORMAT() Funkcja FORMAT() zwraca przekazaną jako pierwszy argument wywołania liczbę z określoną przez drugi parametr liczbą miejsc po przecinku (listing 12.23). Listing 12.23. Formatowanie liczb polega na określaniu miejsc po przecinku SELECT cost_price, FORMAT(cost_price,1), FORMAT(cost_price,3) FROM test.item i; +------------+----------------------+----------------------+ cost_price FORMAT(cost_price,1) FORMAT(cost_price,3) +------------+----------------------+----------------------+ 15.23 15.2 15.230 7.45 7.5 7.450 1.99 2.0 1.990 2.11 2.1 2.110 7.54 7.5 7.540 9.23 9.2 9.230 13.36 13.4 13.360 12
0.75 0.8 0.750 2.34 2.3 2.340 0.01 0.0 0.010 19.73 19.7 19.730 NULL NULL NULL +------------+----------------------+----------------------+ Funkcje daty i czasu Kolejna często używana grupa funkcji to funkcje operujące na argumentach będących zapisem daty lub czasu. W prawie każdej bazie danych część przechowywanych w niej informacji musi mieć jakiś znacznik czasu atrybut pozwalający na sprawdzenie, kiedy rekord został dodany lub zmodyfikowany. Informacje takie jak dane o poszczególnych transakcjach finansowych stają się bezwartościowe po wyeliminowaniu dat tych operacji. Dlatego MySQL posiada predefiniowane funkcje pozwalające wykonywać podstawowe operacje na danych tego typu. CURDATE(), CURTIME() Wynikiem działania funkcji CURDATE() jest bieżąca data, a funkcji CURTIME() bieżący czas. Częstym zastosowaniem funkcji jest automatyczne wstawianie informacji o czasie utworzenia lub zmodyfikowania danych (listing 12.24). Listing 12.24. Odczytanie bieżącej daty i czasu systemowego SELECT CURDATE(),CURTIME(); +------------+-----------+ CURDATE() CURTIME() +------------+-----------+ 2016-04-06 09:33:10 +------------+-----------+ NOW() Funkcja NOW() zwraca zarówno datę, jak i czas systemowy (listing 12.25). Listing 12.25. Przykład wywołania funkcji NOW(). Należy zwrócić uwagę, że nawet jeżeli funkcja wywoływana jest bez parametrów, trzeba użyć nawiasów SELECT NOW(); +---------------------+ NOW() +---------------------+ 2016-04-06 09:37:08 +---------------------+ 13
DAYOFMONTH(), DAYOFWEEK(), DAYOFYEAR() Funkcje DAYOFMONTH(), DAYOFWEEK(), DAYOFYEAR() zwracają numer dnia odpowiednio: miesiąca (liczba z zakresu od 1 do 31), tygodnia (liczba z zakresu od 1 do 7, gdzie 1 oznacza niedzielę pierwszy dzień tygodnia, a 7 sobotę siódmy dzień tygodnia) i roku (liczba z zakresu od 1 do 365) (listing 12.26). Listing 12.26. Lista zamówień złożonych w piątek SELECT * FROM orderinfo WHERE DAYOFWEEK(date_placed) = 6; +--------------+-------------+-------------+--------------+----------+ orderinfo_id customer_id date_placed date_shipped shipping +--------------+-------------+-------------+--------------+----------+ 2 8 2000-06-23 2000-06-23 0.00 5 8 2000-07-21 2000-07-24 0.00 +--------------+-------------+-------------+--------------+----------+ DAY(), MONTH(), YEAR() Funkcje DAY(), MONTH(), YEAR() zwracają odpowiednio dzień, miesiąc i rok z daty przekazanej jako parametr wywołania (listing 12.27). Listing 12.27. Informacja o dacie zamówień rozbita na dni, miesiące i lata SELECT date_placed, DAY(date_placed), MONTH (date_placed), YEAR(date_placed) FROM orderinfo; +-------------+------------------+---------------------+-------------------+ date_placed DAY(date_placed) MONTH (date_placed) YEAR(date_placed) +-------------+------------------+---------------------+-------------------+ 2000-03-13 13 3 2000 2000-06-23 23 6 2000 2000-09-02 2 9 2000 2000-09-03 3 9 2000 2000-07-21 21 7 2000 +-------------+------------------+---------------------+-------------------+ HOUR(), MINUTE(), SECOND() Funkcje HOUR(), MINUTE(), SECOND() zwracają odpowiednio godziny, minuty i sekundy z czasu przekazanego jako parametr wywołania (listing 12.28). Listing 12.28. Informacja o bieżącym czasie rozbita na godziny, minuty i sekundy SELECT HOUR(CURTIME()), MINUTE(CURTIME()), SECOND(CURTIME()); 14
+-----------------+-------------------+-------------------+ HOUR(CURTIME()) MINUTE(CURTIME()) SECOND(CURTIME()) +-----------------+-------------------+-------------------+ 12 50 9 +-----------------+-------------------+-------------------+ DAYNAME(), MONTHNAME() Funkcje DAYNAME(), MONTHNAME() zwracają nazwę dnia tygodnia i miesiąca daty będącej argumentem wywołania (listing 12.29). Listing 12.29. Opisowo przedstawione dni tygodnia i nazwy miesięcy SELECT date_placed, DAYNAME(date_placed), MONTHNAME(date_placed) FROM orderinfo; +-------------+----------------------+------------------------+ date_placed DAYNAME(date_placed) MONTHNAME(date_placed) +-------------+----------------------+------------------------+ 2000-03-13 Monday March 2000-06-23 Friday June 2000-09-02 Saturday September 2000-09-03 Sunday September 2000-07-21 Friday July +-------------+----------------------+------------------------+ DATE_ADD() Działanie funkcji DATE_ADD() powoduje obliczenie wyniku zmiany daty (podanej jako pierwszy parametr) o ilość jednostek czasu określoną przez drugi parametr (listing 12.30). Listing 12.30. Terminy zrealizowania zamówień zostały przesunięte o trzy dni SELECT date_shipped, DATE_ADD(date_shipped, INTERVAL 3 DAY) FROM orderinfo; +--------------+----------------------------------------+ date_shipped DATE_ADD(date_shipped, INTERVAL 3 DAY) +--------------+----------------------------------------+ 2000-03-17 2000-03-20 2000-06-23 2000-06-26 2000-09-12 2000-09-15 2000-09-10 2000-09-13 2000-07-24 2000-07-27 +--------------+----------------------------------------+ 15
DATEDIFF() Wynikiem działania funkcji DATEDIFF() jest liczba dni, które dzielą daty podane jako parametry funkcji. Aby sprawdzić, ile dni upłynęło pomiędzy złożeniem i zrealizowaniem zamówienia, napiszemy (listing 12.31): Listing 12.31. Aliasy zdefiniowane w klauzuli SELECT nie mogą być użyte w innych klauzulach. Zamiast tego musimy powtórzyć całe wyrażenie SELECT orderinfo_id, DATEDIFF(date_shipped, date_placed) AS 'czas realizacji' FROM orderinfo ORDER BY DATEDIFF(date_shipped, date_placed); +--------------+-----------------+ orderinfo_id czas realizacji +--------------+-----------------+ 2 0 5 3 1 4 4 7 3 10 +--------------+-----------------+ DATE_FORMAT(), TIME_FORMAT() Funkcja DATE_FORMAT() pozwala formatować dane daty i czasu, funkcja TIME_FORMAT() pozwala formatować wyłącznie informacje o czasie. Pierwszym parametrem obu funkcji jest data lub czas, drugim symbol docelowego formatu (tabela 12.1). Tabela 12.1. Najczęściej stosowane formaty daty i czasu Format Opis %a Skrócona nazwa dnia tygodnia %b Skrócona nazwa miesiąca %c Jedno- lub dwucyfrowy numer miesiąca %D Kolejny dzień miesiąca z angielskim przedrostkiem %d Jedno- lub dwucyfrowy numer dnia miesiąca %e Dwucyfrowy numer dnia miesiąca %f Liczba milisekund %H Godziny w notacji 24-godzinnej 16
%h Godziny w notacji 12-godzinnej %i Minuty %j Dzień roku %M Nazwa miesiąca %m Dwucyfrowy numer miesiąca %p Symbol AM (łac. ante meridiem) lub PM (łac. post meridiem) %r Czas w formacie hh:mm:ss uzupełniony o symbol AM lub PM %S Sekundy %T Czas w formacie hh:mm:ss %U Tydzień (pierwszym dniem tygodnia jest niedziela) %u Tydzień (pierwszym dniem tygodnia jest poniedziałek) %W Nazwa dnia tygodnia %w Dzień tygodnia %Y Czterocyfrowy rok %y Dwucyfrowy rok Listing 12.32. pokazuje zastosowanie obu funkcji do formatowania danych daty i czasu. Listing 12.32. Daty zrealizowania zamówień w oryginalnym i polskim formacie uzupełnione o informacje o bieżącym czasie SELECT date_shipped, DATE_FORMAT(date_shipped, '%D%M, %Y'), time_format(curtime(),'%t') FROM orderinfo; +--------------+---------------------------------------+-----------------------------+ date_shipped DATE_FORMAT(date_shipped, '%D%M, %Y') time_format(curtime(),'%t') +--------------+---------------------------------------+-----------------------------+ 2000-03-17 17thMarch, 2000 13:13:01 2000-06-23 23rdJune, 2000 13:13:01 2000-09-12 12thSeptember, 2000 13:13:01 2000-09-10 10thSeptember, 2000 13:13:01 2000-07-24 24thJuly, 2000 13:13:01 +--------------+---------------------------------------+-----------------------------+ 17
Funkcje konwersji Piąta wersja serwera MySQL umożliwia definiowanie kolumn lub deklarowanie zmiennych różnych typów: 1. Dane tekstowe (typy char, varchar, text) mogą zawierać tekst lub kombinacje tekstu i liczb, na przykład adres; mogą zawierać również liczby, na których nie są przeprowadzane obliczenia, takie jak numery telefonów, numery katalogowe i kody pocztowe. 2. Dane binarne (typy binary, varbinary, BLOB) mogą zawierać dowolne dane. Mogą to być zarówno długie teksty, jak i grafika czy pliki multimedialne. 3. Dane liczbowe (typy tinyint, smallint, mediumint, int, bigint, decimal, float, double) zawierają dane liczbowe, na których są przeprowadzane obliczenia, przy czym dwa ostatnie typy są zmiennoprzecinkowe, czyli takie dane przechowywane są z określoną dokładnością. 4. Daty (typy datetime, date, timestamp, time i year) przechowują dane dotyczące daty i czasu. 5. Dane logiczne (typy bool, boolean) w MySQL-u są to synonimy typu tinyint, przy czym 0 oznacza fałsz, a 1 prawdę. Prędzej czy później każdy administrator i programista baz danych będzie zmuszony porównać dane różnych typów. Wynik porównania np. imienia Anna z liczbą 712 czy datą 2001-1-1 jest trudny do przewidzenia. Aby takie porównanie było możliwe, trzeba najpierw przekonwertować porównywane dane. ASCII() W wyniku działania funkcji ASCII() będzie zwrócony kod ASCII znaku podanego jako parametr wywołania. Jeżeli jako parametr podamy ciąg znaków, za pomocą tej funkcji zostanie obliczony i zwrócony kod ASCII pierwszego znaku w ciągu (listing 12.33). Listing 12.33. Konwersja znaków na liczby SELECT ASCII(lname), lname FROM customer; +--------------+---------+ ASCII(lname) lname +--------------+---------+ 83 Stones 83 Stones 77 Matthew 77 Matthew 67 Cozens 77 Matthew 83 Stones 83 Stones 72 Hickman 18
72 Howard 74 Jones 78 Neill 72 Hendy 78 Neill 72 Hudson 87 Wolski +--------------+---------+ CHR() Działanie funkcji CHR() jest przeciwieństwem działania funkcji ASCII() zamiast zamiany tekstu na liczbę przeprowadza konwersję liczby na odpowiadające jej znaki kodu ASCII (listing 12.34). Listing 12.34. Funkcję CHR() często stosuje się w celu oszukania prostych zabezpieczeń przed iniekcją kodu SELECT CHAR(77,121,83,81,'76'); +-------------------------+ CHAR(77,121,83,81,'76') +-------------------------+ MySQL +-------------------------+ BIN() Funkcja BIN() zwraca binarną reprezentację podanej liczby dziesiętnej (listing 12.35). Listing 12.35. Zmiana podstawy liczb SELECT item_id, BIN(item_id) FROM item; +---------+--------------+ item_id BIN(item_id) +---------+--------------+ 1 1 2 10 3 11 4 100 5 101 6 110 7 111 8 1000 9 1001 10 1010 11 1011 12 1100 +---------+--------------+ 19
CAST() Funkcja CAST() pozwala przekonwertować (rzutować) dane przekazane jako pierwszy parametr wywołania na typ podany jako drugi parametr funkcji (listing 12.36). Listing 12.36. CAST() jest najbardziej uniwersalną funkcją konwersji SELECT CAST('2001-1-1' AS date); CAST('2001-1-1' AS date) 2001-01-01 Funkcje serwera MySQL Kilka funkcji kryptograficznych dostępnych w serwerze MySQL. ENCODE(), DECODE() Funkcja ENCODE() zwraca szyfrogram podanego ciągu znaków. Do szyfrowania używane jest hasło podane jako drugi parametr wywołania (listing 12.37). Funkcja DECODE() deszyfruje zaszyfrowane funkcją ENCODE() szyfrogramy. Listing 12.37. Poufne dane lepiej przechowywać w bazie w postaci zaszyfrowanej SELECT ENCODE('Pin do karty VISA GOLD to 3478','h@ssL0'); +---------------------------------------------------+ ENCODE('Pin do karty VISA GOLD to 3478','h@ssL0') +---------------------------------------------------+ ćň5)kâw őu +---------------------------------------------------+ SHA1() Funkcja SHA1() wylicza sygnaturę podanego ciągu znaków (listing 12.38). Listing 12.38. W niektórych przypadkach trzeba móc potwierdzić autentyczność danych. Najlepiej wykorzystać do tego funkcję mieszania SELECT SHA1(sell_price) FROM item; +------------------------------------------+ SHA1(sell_price) +------------------------------------------+ d593b090a756bf12bb1b40e50d03db971d90865a 366091419860e27172808dce4b1be574bb51c5fe 03f82d768c8366b01cc7366f3c2628e0ec9a8021 20
70d403dc3c9428c27b2da0056c4702e424c928b1 8818c759d88e34a1184655ed00ae1a44121aabd5 3194b173d1f5e493d10d8fe69cdbb6a9ae218c0e 866de6c5b3f877858098c63bd9f5fb67b3616736 2792cf2449e7d1a4a46d0b78eb2caeb99e78a396 953e85433144f4cec72744beca1c8eeb898df5d8 22cf82b68b95049bffb91128349ccc312a460b10 139fb724c5c37892cb113d2866672b67e9a90ff9 NULL +------------------------------------------+ PASSWORD() Hasła użytkowników muszą być chronione, a to oznacza, że nigdy nie należy zapisywać ich w bazie w jawnej postaci. Prawie zawsze hasło wykorzystywane jest jedynie do potwierdzenia tożsamości użytkownika, a do tego celu serwer baz danych nie musi odszyfrować hasła, czyli hasła powinny być zapisane nieodwracalnie zaszyfrowane. Wiemy już, że tak działają funkcje mieszania hasła do serwera MySQL też są tak przechowywane, z tym że do ich wyliczenia i późniejszego porównania wykorzystywana jest funkcja PASSWORD() (listing 12.39). Listing 12.39. Do sprawdzania tożsamości należy używać sygnatur haseł, nie samych haseł SELECT fname, lname FROM customer WHERE PASSWORD (fname) = '*773326F7387809AEE1566F9BEDE2DEE006776333'; +-----------------+ fname lname +-----------------+ Alex Matthew +-----------------+ SELECT PASSWORD ('Jenny'); +-------------------------------------------+ PASSWORD ('Jenny') +-------------------------------------------+ *B2D8022EC63D192D46A9C6E8F651C37B4BC163A6 +-------------------------------------------+ SELECT fname, lname FROM customer WHERE PASSWORD (fname) = '*B2D8022EC63D192D46A9C6E8F651C37B4BC163A6'; +----------------+ fname lname +----------------+ Jenny Stones +----------------+ 21