Bazy Danych i Systemy informacyjne Wykład 4 Piotr Syga 26.10.2018
Procedury review Przypomnienie składni procedur Tworzenie DELIMITER $$ CREATE PROCEDURE zliczacz (OUT wynik INT) BEGIN operacje... END $$ DELIMITER ;
Pętle i kursory Pętle LOOP etykieta LOOP komendy END LOOP etykieta; WHILE (etykieta) WHILE komendy END WHILE (etykieta);
Pętle i kursory Przykłady Przykład loop CREATE PROCEDURE ShaltThouCountToThree(c INT) BEGIN countloop: LOOP IF c > 3 THEN SET c = 0; ITERATE countloop; ELSEIF c < 3 THEN SET c = c + 1; ITERATE countloop; ELSE LEAVE countloop; END IF; END LOOP countloop; SET @countnumber = c; END;
Pętle i kursory Przykłady Przykład while CREATE PROCEDURE ThreeShaltBeTheNumberThouShaltCount(c INT) BEGIN IF c > 3 THEN SET c = 0; END IF; WHILE c < 3 THEN SET c = c + 1; END WHILE; SET @countnumber = c; END;
Pętle i kursory Kursory idea Umożliwienie iteracji po wyniku zapytania Brak możliwości update u tabel przez kursor Brak możliwości skoków po wyniku Asensitive vs Insensitive
Pętle i kursory Kursory używanie 1 Tworzenie: DECLARE cursor_name CURSOR FOR (SELECT... ); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 2 Inicjacja: OPEN cursor_name; 3 Pobieranie: FETCH cursor_name INTO (... ); 4 Zamykanie: CLOSE cursor_name;
Pętle i kursory Kursory przykład DELIMITER // CREATE PROCEDURE p1() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE C,I INT; DECLARE ConcertCount CURSOR FOR (SELECT zespol, count(*) as number FROM Koncerty GROUP BY zespol); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN ConcertCount; read_loop: LOOP FETCH ConcertCount INTO I,C; IF done THEN LEAVE read_loop; END IF; IF C > 10 THEN SELECT z.name FROM Zespoly z WHERE z.id=i; END IF; END LOOP; CLOSE ConcertCount; END; //
Szukanie i uaktualnianie Dla przypomnienia update Używanie kilku tabel UPDATE Koncerty k JOIN Zespoly z ON z.id = k.zespol AND z.kraj = USA SET k.data = DATE_ADD(k.data, INTERVAL 7 DAY) WHERE k.miejsce = Black Rock Desert AND k.data>now();
Szukanie i uaktualnianie Indexy Idea zapamiętanie wartości w kolumnie (części kolumny lub kolumnach) w celu uniknięcia przetwarzania każdego wiersza poprawa efektywności kosztem miejsca korzystanie z indeksów odbywa się automatycznie, optimizer decyduje kiedy skorzystać z indeksów podobne zapytania mogą być traktowane odmiennie: LIMIT, LIKE %abc vs abc%
Szukanie i uaktualnianie Indexy Tworzenie Zawsze istnieje przynajmniej jeden index w tabeli CREATE INDEX name_idx USING BTREE ON Studenci (nazwisko, imię); możemy utworzyć indeks z wykorzystaniem części kolumny Uwagi: Indeksy wielokolumnowe tworzone są przez konkatenacje. Aby wykorzystywać indeks w zapytaniu wszystkie klauzule koniunkcji muszą wykorzystywać indeks. Struktury: B-drzewa, R-drzewa, Hashe
Szukanie i uaktualnianie Indeksy przykłady SELECT * FROM Studenci WHERE nazwisko LIKE Kowals% ; SELECT * FROM Studenci WHERE nazwisko LIKE %ski ; SELECT * FROM Studenci WHERE imię LIKE Ja% ; SELECT * FROM Studenci JOIN Studenci s ON Studenci.imię=s.imię WHERE s.nazwisko < Studenci.nazwisko;
Szukanie i uaktualnianie Indeksy koszty zużywana pamięć spowolnienie INSERT modyfikacja tabel i nie używane indeksy (EXPLAIN) problem Halloweenowy
Szukanie i uaktualnianie Indeksy koszty Halloween Problem Problem zdiagnozowany w 1976 (Chamberlin, Sellinger, Astrahan) Halloweenowa podwyżka dla pracowników zarabiających poniżej $25.000 rocznie: UPDATE EMPLOYEE SET SALARY = SALARY * 1.1 WHERE SALARY<25000 Po wykonaniu zapytania nie było pracowników zarabiających mniej niż $25.000 gdzie leży problem? Przykład rozwiązania problemu na podstawie T-SQL.
Transakcje Idea, czyli po co nam transakcje? Prosty scenariusz Załóżmy, że logujemy się na stronę banku i chcemy wykonać przelew ze swojego konta A na obce konto B (dla uproszczenia w tym samym banku). Pomińmy rozważania kwestii bezpieczeństwa. Klikamy wysłanie przelewu, jednak w momencie przesłania informacji, na skutek awarii połączenie z bazą danych zostało zerwane. Jaki jest efekt operacji?
Transakcje Możliwe opcje Opcja 1 Po kliknięciu wysłania, odpowiednia kwota została odpisana z konta A Połączenie zostało zerwane nim kwota została dopisana do konta B Efekt: Straciliśmy pieniądze, operacja nie została wykonana, zarabia bank
Transakcje Możliwe opcje Opcja 1 Po kliknięciu wysłania, odpowiednia kwota została odpisana z konta A Połączenie zostało zerwane nim kwota została dopisana do konta B Efekt: Straciliśmy pieniądze, operacja nie została wykonana, zarabia bank Opcja 2 Po kliknięciu wysłania, odpowiednia kwota została dopisana do konta B Połączenie zostało zerwane nim kwota została odjęta od stanu konta A Efekt: Wykreowaliśmy pieniądze (przywilej jedynie NBP) lub pomniejszyliśmy rezerwę banku
Transakcje Rozwiązanie problemu Cel Chcemy zrealizować podejście all-or-nothing, warunkując wykonanie jednej operacji drugą wykonać obie operacje jako jedną atomową instrukcję. Realizacja SET autocommit = 0; START TRANSACTION; SELECT @s:=saldo FROM rachunek WHERE num=a; UPDATE rachunek SET saldo=@s-kwota WHERE num=a; SELECT @s2:=saldo FROM rachunek WHERE num=b; UPDATE rachunek SET saldo=@s2+kwota WHERE num=b; COMMIT;
Transakcje Zagnieżdżanie MySQL SAVEPOINT identifier ROLLBACK [WORK] TO [SAVEPOINT] identifier RELEASE SAVEPOINT identifier Uwagi: 1 nazwanie savepointa nie rozpoczyna transakcji 2 powtórzenie savepointa nadpisuje stary
Transakcje Rollback ma swoje ograniczenia Tworzenie(CREATE), usuwanie(drop) i zmienianie(alter) (oraz RENAME): baz danych (i użytkowników) tabel, widoków, index procedur, funkcji, triggerów MySQL po wywołaniu powyższych kwerend, komituje aktualną transakcję przed wykonaniem kwerendy.