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ę.
Funkcje tekstowe zwracające tekst
CONCAT()
Funkcja łączy (konkatenuje) przekazane jako parametr i oddzielone przecinakami 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 przecinakami 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 5.1):
Listing 5.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 5.2):
Listing 5.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 |
| 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 5.3.
Listing 5.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 |
| |
+--------------------------------------+
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 5.4).
Listing 5.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 5.5).
Listing 5.5. Przed zapisaniem danych do bazy z reguły warto usunąć z nich przypadkowo dodane spacje
SELECT ltrim(' barba dos '), rtrim(' barba dos '), trim(' barba dos ');
+---------------------------+---------------------------+-----------------------
---+
| ltrim(' barba dos ') | rtrim(' barba dos ') | trim(' barba dos
') |
+---------------------------+---------------------------+-----------------------
---+
| barba dos | 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 5.6).
Listing 5.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 5.7).
Listing 5.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 5.8).
Listing 5.8. Zamiast ręcznie dodawać spacje, możemy użyć do tego funkcji SPACE()
SELECT CONCAT(fname, SPACE(3), lname)
FROM customer;
+--------------------------------+
| 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 |
| |
+--------------------------------+
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 5.9).
Listing 5.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 5.10).
Listing 5.10. Funkcja LENGTH() użyta do selekcji wierszy
SELECT description, LENGTH(description)
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 5.11).
Listing 5.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 5.12).
Listing 5.12. Przykład użycia funkcji ROUND()
SELECT Round(3.1415926535897,4) , Round(3.1415926535897,0),
Round(3.1415926535897);
+--------------------------+--------------------------+------------------------+
| Round(3.1415926535897,4) | Round(3.1415926535897,0) | Round(3.1415926535897) |
+--------------------------+--------------------------+------------------------+
| 3.1416 | 3 | 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 5.13).
Listing 5.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 5.14).
Listing 5.14. Funkcja ABS() użyta do sprawdzenia, czy dana liczba jest dodatnia
SELECT *
FROM item
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 5.15).
Listing 5.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 5.16).
Listing 5.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 |
+-------------+-----------+
SQRT()
W wyniku działania funkcji SQRT() zwrócony będzie pierwiastek kwadratowy z liczby podanej jako parametr wywołania (listing 5.17).
Listing 5.17. Przykład użycia funkcji SQRT()
SELECT SQRT(10), SQRT(16);
+-----------------+----------+
| SQRT(10) | SQRT(16) |
+-----------------+----------+
| 3.1622776601684 | 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 5.18).
Listing 5.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 5.19).
Listing 5.19. Przykład użycia funkcji trygonometrycznych
SELECT SIN(200), COS(200), COT(200);
+-------------------+------------------+-------------------+
| 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 5.20), co pozwala użyć funkcji RAND() do losowego wybierania danych z tabeli (listing 5.21).
Listing 5.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 5.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 |
+---------+-------------+------------+------------+
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 5.22 użyto jej do wyróżniania informacji o tym, czy cena sprzedaży towaru była wyższa od ceny jego zakupu.
Listing 5.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 5.23).
Listing 5.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 |
| 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 5.24).
Listing 5.24. Odczytanie bieżącej daty i czasu systemowego
SELECT CURDATE(),CURTIME();
+------------+-----------+
| CURDATE() | CURTIME() |
+------------+-----------+
| 2009-08-20 | 09:33:10 |
+------------+-----------+
NOW()
Funkcja NOW() zwraca zarówno datę, jak i czas systemowy (listing 5.25).
Listing 5.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() |
+---------------------+
| 2009-08-20 09:37:08 |
+---------------------+
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 5.26).
Listing 5.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 5.27).
Listing 5.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 5.28).
Listing 5.28. Informacja o bieżącym czasie rozbita na godziny, minuty i sekundy
SELECT HOUR(CURTIME()), MINUTE(CURTIME()), SECOND(CURTIME());
+-----------------+-------------------+-------------------+
| 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 5.29).
Listing 5.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 5.30).
Listing 5.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 |
+--------------+----------------------------------------+
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 5.31):
Listing 5.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 5.1).
Tabela 5.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 |
%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 5.32. pokazuje zastosowanie obu funkcji do formatowania danych daty i czasu.
Listing 5.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
|
+--------------+---------------------------------------+------------------------
-----+
Funkcje konwersji
Piąta wersja serwera MySQL umożliwia definiowanie kolumn lub deklarowanie zmiennych różnych typów:
- 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.
- Dane binarne (typy binary, varbinary, BLOB) — mogą zawierać dowolne dane. Mogą to być zarówno długie teksty, jak i grafika czy pliki multimedialne.
- 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ą.
- Daty (typy datetime, date, timestamp, time i year) — przechowują dane dotyczące daty i czasu.
- 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 5.33).
Listing 5.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 |
| 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 5.34).
Listing 5.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 5.35).
Listing 5.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 |
+---------+--------------+
CAST()
Funkcja CAST() pozwala przekonwertować (rzutować) dane przekazane jako pierwszy parametr wywołania na typ podany jako drugi parametr funkcji (listing 5.36).
Listing 5.36. CAST() jest najbardziej uniwersalną funkcją konwersji
SELECT CAST('2001-1-1' AS date);
+--------------------------+
| CAST('2001-1-1' AS date) |
+--------------------------+
| 2001-01-01 |
+--------------------------+
Funkcje kryptologiczne
Kryptologia to dziedzina nauki zajmująca się zabezpieczeniem informacji. Obejmuje ona kryptografię — jej dziedziną jest szyfrowanie danych — i opisującą techniki łamania szyfrów kryptoanalizę.
Kodowanie a szyfrowanie
Kodowanie i szyfrowanie nie są tym samym. Kodowanie polega na zapisywaniu wyrażeń jednego języka za pomocą wyrażeń innego języka. W informatyce ten drugi język sprowadza się najczęściej do zerojedynkowych ciągów bitów, stanowiących wewnętrzny język komputera (rysunek 5.1).
|
Rysunek 5.1. Proces kodowania danych |
Kodowanie ma na celu takie przetworzenie pierwotnych danych, aby można było optymalnie je przechowywać lub przesyłać, a nie uniemożliwienie ich odczytania przez niepowołane osoby. Aby odczytać zakodowane dane, wystarczy znać zasadę działania dekodera (algorytm dekodowania).
Natomiast szyfrowanie jest odmianą kodowania, w której wymagamy, aby kod nie ujawniał zawartych w szyfrogramie informacji. W tym celu koder, nazywany szyfratorem lub enkryptorem, do utworzenia szyfrogramu (nazywanego też kryptogramem) wykorzystuje dodatkową informację — klucz. Odszyfrowanie danych wymaga użycia klucza, sama znajomość algorytmu dekodowania do tego nie wystarcza. Klucz powinny znać tylko osoby lub programy, dla których szyfrowane dane są przeznaczone; bezpieczeństwo szyfrogramu zależy od jakości algorytmu szyfrującego i stopnia skomplikowania(głównie długości) klucza. Ogólny schemat szyfrowania przedstawia rysunek 5.2.
|
Rysunek 5.2. Proces szyfrowania danych |
Zasada Kerckhoffsa
Załóżmy następującą sytuację: Alicja chce przekazać Bobowi pewną informację, ale wszystkie przesyłane do niego wiadomości przechwytuje Ewa (rysunek 5.3).
|
Rysunek 5.3. W kryptologii Alicja oznacza nadawcę wiadomości, Bob — odbiorcę, a Ewa — pozostałych użytkowników systemu |
Gdyby udało nam się uniemożliwić Ewie odczytanie przesyłanych pomiędzy Alicją i Bobem wiadomości, rozwiązalibyśmy również problem zabezpieczenia przesyłanych w drugą stronę odpowiedzi oraz zabezpieczenia danych zapisanych na ogólnie dostępnych nośnikach (w tym ostatnim przypadku wystarczy wyobrazić sobie, że zapisane na dysku dane „wędrują” w czasie od Alicji do Boba).
Dlaczego tego zadania nie można rozwiązać za pomocą kodowania? Odpowiedzią jest zasada Kerckhoffsa. Auguste Kerckhoffs jest autorem jednej z podstawowych zasad współczesnej kryptografii — bezpieczeństwo szyfrogramu powinno zależeć wyłącznie od ukrycia klucza, a nie ukrycia algorytmu użytego do szyfrowania i deszyfrowania. Czyli ujawnienie algorytmów nie może wiązać się ze zwiększeniem ryzyka złamania szyfru. Dlaczego ta zasada jest tak ważna? Przede wszystkim dlatego, że algorytmy są powszechnie wykorzystywane — wszyscy użytkownicy danego systemu muszą dysponować programem szyfrującym i deszyfrującym dane, a więc programem, który zawiera użyte algorytmy szyfrowania. Informacji powszechnie dostępnej nie można skutecznie ukryć.
Wróćmy do problemu Alicji i Boba. Skoro Ewa ma możliwość podsłuchiwania przesyłanych wiadomości, to Alicja musi wysyłać je zaszyfrowane (c), a nie w postaci jawnego tekstu (m). Do szyfrowania wykorzysta funkcję szyfrującą (nazwijmy ją E) i wcześniej uzgodniony z Bobem klucz Ke (rysunek 5.4).
|
Rysunek 5.4. Ewa ma dostęp do szyfrogramu, ale nie do tekstu otwartego |
Podstawowym problemem, który wymaga rozwiązania, jest sposób wymiany klucza Ke pomiędzy Alicją i Bobem — szyfrowanie wymaga współdzielenia jakiegoś sekretu. Do tego problemu wrócimy, opisując algorytmy szyfrowania asymetrycznego. Inny problem polega na uniemożliwieniu Ewie zdobycia informacji o wiadomości m na podstawie przechwyconego szyfrogramu c. Wbrew pozorom szyfrogram zawiera sporo danych na temat tekstu jawnego — wśród nich:
-
czas przesłania wiadomości (ukrycie tej informacji jest praktycznie niemożliwe);
-
jej rozmiar (ukrycie tej informacji jest bardzo trudne);
-
strukturę tekstu jawnego (dobre systemy kryptograficzne minimalizują wycieki tej informacji).
Klucze
Klucz jest ciągiem bitów wykorzystywanym przez wszystkie algorytmy szyfrowania w procesie szyfrowania lub deszyfrowania danych. Znajomość zarówno algorytmu, jak i klucza użytego do zaszyfrowania danych jest niezbędna do ich odszyfrowania. Wynika z tego, że jeżeli kilku użytkowników zna dany klucz, to każdy z nich może odszyfrować zaszyfrowaną danym algorytmem wiadomość.
Bezpieczeństwo zaszyfrowanych danych zależy wprost proporcjonalnie od długości klucza wykorzystanego do utworzenia szyfrogramu. Aby na przykład bez znajomości klucza, metodą pełnego przeglądu (czyli sprawdzania wszystkich kombinacji), odszyfrować dane zaszyfrowane za pomocą klucza o długości 10 bitów, należy sprawdzić 210 (1024) kombinacji. Natomiast odszyfrowanie danych zaszyfrowanych za pomocą klucza o długości 56 bitów będzie wymagać sprawdzenia już 256 (72 057 594 037 927 936) kombinacji. Przy mocy obliczeniowej, jaką dysponują dzisiejsze komputery, za bezpieczne uważa się klucze o długości co najmniej 128 bitów.
W przypadku opisanego w dalszej części rozdziału szyfrowania asymetrycznego minimalna długość bezpiecznego klucza wynosi 1024 bity.
Funkcje mieszania
Funkcje mieszania (ang. Hash) są funkcjami jednokierunkowymi, czyli teoretycznie niemożliwe jest odtworzenie oryginalnych danych na podstawie znajomości wyliczonego za ich pomocą ciągu bajtów. W tym sensie do funkcji mieszania można by też zaliczyć np. funkcję modulo, jednak kryptograficzne funkcje mieszania musi cechować maksymalna losowość wyniku, minimalna szansa zwrócenia tego samego wyniku dla różnych wiadomości i maksymalne zróżnicowanie wyniku dla niewielkich zmian wiadomości.
Funkcje mieszania dla dowolnego zbioru danych zwracają sygnaturę o ściśle określonej długości. W ten sposób niemożliwe jest wyliczenie wielkości zbioru danych źródłowych na podstawie przechwyconej wartości funkcji skrótu. Funkcje mieszania nie umożliwiają szyfrowania danych, ale doskonale nadają się do sprawdzenia, czy oryginalne dane nie zostały zmodyfikowane. W tym celu wystarczy np. wyliczyć wartość funkcji mieszania dla wysłanej wiadomości e-mail czy zapisanego na dysku twardym pliku, a potem porównać ją z wartością wyliczoną przez odbiorcę wiadomości. Jeżeli oba wyniki są identyczne, to znaczy, że dane nie zostały zmodyfikowane.
Współcześnie powszechnie stosowane są dwie funkcje skrótu:
1. MD5 (ang. Message Digest Algorithm 5) — funkcja skrótu zdefiniowana w dokumencie RFC 1231, szybka, ale nieuważana już za bezpieczną, zwraca wyniki o długości 128 bitów.
Za pomocą dostępnych w internecie programów (np. pod adresem http://www.stachliu.com/collisions.html można znaleźć program Patrick Stach) każdy na domowym komputerze w ciągu kilkudziesięciu minut może wygenerować skrót MD5 kolidujący z podanym.
2. SHA-1 (ang. Secure Hash Algorithm) — funkcja mieszania wolniejsza, ale bezpieczniejsza od poprzedniej, tworząca wyniki o długości 160 bitów. Funkcja ta jest standardem stosowanym przez agencje rządowe Stanów Zjednoczonych Ameryki Północnej.
Dodatkowym ryzykiem związanym ze stosowaniem funkcji skrótu jest ich podatność na ataki urodzinowe(ang. Birthday attack). Nazwa ataku pochodzi od ciekawego paradoksu — w grupie 23 osób prawdopodobieństwo, że dwie osoby obchodzą tego samego dnia urodziny (prawdopodobieństwo kolizji), przekracza 50 procent. Ataki tego typu wykorzystują fakt, że znalezienie zbioru danych, dla którego wyliczona funkcja skrótu będzie taka sama jak dla oryginalnego zbioru, jest wielokrotnie łatwiejsze niż odgadnięcie tego zbioru.
Kolizje
Im większy zakres generowanych danych, tym mniejsze jest ryzyko powtórzenia tej samej wartości (kolizji). Na przykład przy rzucie kostką (6 możliwości) ryzyko, że dwa razy otrzymamy ten sam wynik, jest dużo większe niż przy wybieraniu karty z talii (48 możliwości). Pytanie brzmi: „O ile większe jest ryzyko wystąpienia kolizji w pierwszym przypadku?”, czyli „Jak często występują kolizje?”. Okazuje się, że występują o wiele częściej, niżby się mogło wydawać. Z dość dużym przybliżeniem możemy przyjąć, że dla zbioru N możliwych wartości pierwsza kolizja wystąpi po wybraniu wartości.
Wróćmy do paradoksu urodzinowego: rok liczy 365 dni, czyli pierwsza kolizja (powtórzenia dnia urodzin) wystąpi po mniej więcej (19) próbach. Z 20-osobowej grupy możemy utworzyć n(n – 1)/2 (190) par, dla każdej z nich prawdopodobieństwo, że obie osoby obchodzą urodziny tego samego dnia, wynosi 1/365. Całkowite ryzyko wystąpienia kolizji wynosi więc n(n – 1)/2 · 1/365 (380/730), czyli ponad 50%.
W rzeczywistości ryzyko wystąpienia kolizji jest nieco mniejsze niż pierwiastek z liczby możliwych wartości, dlatego ponad 50-procentowa szansa na podwójne urodziny wystąpi w grupie 23-osobowej.
Tak duże ryzyko wystąpienia kolizji oznacza, że pierwsze powtórzenie klucza o długości 64 bitów będzie miało miejsce po wygenerowaniu 232 (4 294 967 296) wiadomości. Czy to dużo? Nie, to stanowczo zbyt mało, żeby można było mówić o bezpieczeństwie systemu. Dlatego przyjmuje się, że bezpieczeństwo (siła) systemu kryptograficznego jest równa co najwyżej pierwiastkowi długości wykorzystywanych w nim kluczy. A to z kolei jest powodem, dla którego w żadnym wypadku nie należy używać kluczy krótszych niż 128-bitowe.
Funkcje serwera MySQL
Po tym krótkim wprowadzeniu pora przedstawić 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 5.37). Funkcja DECODE() deszyfruje zaszyfrowane funkcją ENCODE() szyfrogramy.
Listing 5.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 5.38).
Listing 5.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 |
| 70d403dc3c9428c27b2da0056c4702e424c928b1 |
| 8818c759d88e34a1184655ed00ae1a44121aabd5 |
| 3194b173d1f5e493d10d8fe69cdbb6a9ae218c0e |
| 866de6c5b3f877858098c63bd9f5fb67b3616736 |
| 2792cf2449e7d1a4a46d0b78eb2caeb99e78a396 |
| 953e85433144f4cec72744beca1c8eeb898df5d8 |
| 22cf82b68b95049bffb91128349ccc312a460b10 |
| 139fb724c5c37892cb113d2866672b67e9a90ff9 |
| |
+------------------------------------------+
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 5.39).
Listing 5.39. Do sprawdzania tożsamości należy używać sygnatur haseł, nie samych haseł
SELECT fname, lname
FROm customer
WHERE PASSWORD (fname) = '*773326F7387809AEE1566F9BEDE2DEE006776333'
Funkcje specjalne
Oprócz funkcji opisanych w poprzednich punktach każdy serwer bazodanowy obsługuje pewną liczbę funkcji specjalnych, systemowych i metadanych. W tym miejscu zwrócimy uwagę tylko na dwie często wykorzystywane funkcje specjalne serwera MySQL.
LAST_INSERT_ID()
Funkcja LAST_INSERT_ID() zwraca ostatni identyfikator wygenerowany podczas wstawiania przez bieżącego użytkownika wiersza do tabeli. Tego typu informacje są z reguły potrzebne programistom aplikacji klienckich, żeby mogli oni powiązać wstawiony właśnie wiersz z wcześniej zapisanymi w bazie danymi (listing 5.40).
Listing 5.40. Zakresem działania funkcji LAST_INSERT_ID() jest pojedyncza sesja, a więc nie zwróci ona identyfikatorów wierszy wstawionych przez innych użytkowników
INSERT INTO item (description, cost_price, sell_price)
VALUES ("SQL. Praktyczny kurs",30.02, 35.99);
Query OK, 1 row affected (0.05 sec)
SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 13 |
+------------------+
LOAD_FILE()
Funkcja LOAD_FILE() pozwala wczytać zawartość pliku (listing 5.41).
Listing 5.41. Funkcja LOAD_FILE() może być używana między innymi do wczytywania danych binarnych lub — jak w tym przypadku — dokumentów XML
SELECT load_file('c:/Test/doc.xml');