StoredProcedures_wykład Plik
Transkrypt
StoredProcedures_wykład Plik
Politechnika Śląska Instytut Informatyki LABORATORIUM BAZ DANYCH IBM DB2 – Procedury składowane Opracowanie: Aleksandra Werner Gliwice 2005 Laboratorium Baz Danych. IBM DB2 – procedury Spis treści 1 2 WPROWADZENIE ........................................................................................... 1 PODSTAWOWA STRUKTURA PROCEDURY ................................................ 3 2.1 Parametry ............................................................................................................................................. 4 2.1.1 Typy danych ................................................................................................................................. 4 2.2 Własności procedury ........................................................................................................................... 5 2.2.1 Otrzymywanie zbioru wynikowego .............................................................................................. 6 2.3 Parametry kontrolne procedury, kontrolujące sposób tworzenia procedury ................................ 7 2.4 Ciało procedury ................................................................................................................................... 7 2.4.1 Rejestry ......................................................................................................................................... 8 3 3.1 4 WYKONYWANIE PROCEDUR ........................................................................ 8 Dynamiczny SQL ................................................................................................................................. 9 ELEMENTY JĘZYKA SQL PL ......................................................................... 9 4.1 Sekwencje ........................................................................................................................................... 10 4.2 Instrukcje sterujące ........................................................................................................................... 10 4.3 Kursory ............................................................................................................................................... 11 4.3.1 Kursory FOR UPDATE .............................................................................................................. 12 4.3.2 Kursory WITH HOLD ................................................................................................................ 12 4.3.3 Kursory READ ONLY ............................................................................................................... 12 4.3.4 Kursory WITH RETURN ........................................................................................................... 13 4.4 Podstawowa obsługa błędów ............................................................................................................. 13 4.4.1 SQLCODE/SQLSTATE ............................................................................................................. 13 4.4.2 Deklaracja warunku i zgłoszenia CONDITION FOR ................................................................. 13 4.4.3 SIGNAL/RESIGNAL ................................................................................................................. 14 4.4.4 GET DIAGNOSTICS ................................................................................................................. 15 4.5 Złożony SQL ...................................................................................................................................... 15 5 5.1 5.2 PROCEDURY ................................................................................................. 16 External Stored Procedures .............................................................................................................. 16 Procedury rejestrowe (registering stored procedures) ................................................................... 16 6 SQL – PSM (ROZSZERZENIA PERSISTENT STORED MODULE) - JĘZYK SKRYPTOWY DO DEKLARACJI I ZARZĄDZANIA PROCEDURAMI.................... 17 6.1 6.2 6.3 7 8 Kompilacja procedury ...................................................................................................................... 17 Etapy wdrażania procedur ............................................................................................................... 17 Opcje kompilacji i reoptymalizacji .................................................................................................. 17 KONCEPCJA NAZYWANIA PROCEDUR ..................................................... 18 UDF ................................................................................................................ 18 -2- IBM DB2 – Procedury składowane 1 1 Wprowadzenie Procedury składowane są obiektami aplikacji bazodanowej. Procedury są nazwanymi blokami PL/SQL'a, które mogą pobierać parametry i być wykonywane. Rozróżnia się dwa typy podprogramów: procedury i funkcje. − − − − − procedury pozwalają na enkapsulację kodu, co poprawia m.in. debugowanie zmiany w schemacie bazy wpływają na zmianę kodu źródłowego tylko w jednym miejscu, co jest raczej zadaniem DBA a nie rewizji całego kodu ponieważ procedury składowane rezydują na serwerze, można za ich pomocą ściślej kontrolować bezpieczeństwo przestrzeni klienta ponieważ procedury składowane są kompilowane i przechowywane poza aplikacją, mogą używać takich zmiennych w SQL-u jak: hasła i dane osobowe, których zwykle unika się w skryptach czy zdalnych wywołaniach redukują ruch w sieci. DB2 pozwala na kodowanie procedur w dowolnym, potrzebnym języku. Istnieją dwa rodzaje procedur składowanych: 1. procedury SQL 2. procedury zewnętrzne - zwykle pisane w C, a obecnie w Javie, COBOL-u, C++, Visual Basic-u, REXX-ie. - jednym z typów są Java stored procedures. Wywołanie procedury składowanej jest traktowane jako zwykłe wywołanie zewnętrzne. Procedura może być wywoływana lokalnie (na tym samym systemie, co działająca aplikacja) lub na innym systemie. Procedury składowane są użyteczne w środowisku rozproszonym, gdyż poprawiają wydajność rozproszonych aplikacji przez redukcję ruchu informacji w sieci komunikacyjnej. Np. jeżeli aplikacja kliencka potrzebuje wykonać kilka operacji bazodanowych na serwerze zdalnym, można wydać wiele różnych żądań bazodanowych ze strony klienta lub wywołać procedurę składowaną. W pierwszym przypadku startuje się dialog z systemem zdalnym za każdym razem, gdy wydaje się jakieś żądanie. W przypadku drugim – tylko ządanie wywołania (call) i parametry przekazywane są po linii. Tak więc procedury składowane mogą być używane dla różnych celów aplikacyjnych: wykonania sekwencji operacji na zdalnej maszynie kontroli dostępu do obiektów bazodanowych wykonania niebazodanowych funkcji Wyobraźmy sobie następującą sytuację: Pewne przedsiębiorstwo ma kilka central, w których znajdują się serwery i oddziałów, w których znajdują się systemy klienckie. Użytkownicy oddziałów pracują na aplikacji FAKTURA, która aktualizuje 3 tabele na serwerze: 1. tabelę FAKTURA 2. tabelę KLIENT 3. tabelę SALDO Rekord faktury jest zaznaczany (flagowany) markerem „czyszczącym”, a następnie odpowiedni rekord tabeli KLIENT jest aktualizowany przez odliczenie kwoty faktury od bieżącej (całkowitej) kwoty znajdującej się na koncie. Na koniec, aktualizowane jest saldo. Poniższy diagram ilustruje aplikację rozproszoną, która była zaimplementowana bez ??? procedur składowanych. IBM DB2 – Procedury składowane 2 Aplikacja rozproszona bez procedur system klienta Server UPDATE faktury faktura UPDATE klienta klient UPDATE salda saldo oddział Aplikacja rozproszona z procedurą Centrala mojaproc UPDATE faktury faktura EXEC SQL UPDATE klienta CALL mojaproc ENDEXEC klient UPDATE salda saldo Porównanie procedut składowanych, triggerów i UDF-ów. Procedury składowane wywołanie środowisko język metoda konwersacji wykonanie polecenia CALL rozproszone/nierozproszone aplikacje jakikolwiek program zawierający JAVA jawne, dwustronne przekazywanie parametrów Triggery UDF bazodanowe WE/WY jako funkcja w zdaniu SQL rozproszone/nierozproszone aplikacje jakikolwiek program zawierający JAVA niejawne przesyłanie parametrów systemu rozproszone/nierozproszone aplikacje jakikolwiek program zawierający JAVA jawne, dwustronne przekazywanie parametrów DB2 ma swój język „DB2 SQL Procedural Language - SQL PL”. Ten język jest używany nie tylko w procedurach składowanych, ale również w funkcjach użytkownika UDFs, triggerach i dynamicznym SQL-u. Oto przykład procedury SQL, która może być użyta do kontroli operacji bazodanowej. -2- IBM DB2 – Procedury składowane 3 CREATE PROCEDURE administrator.update_sal ( IN empNum CHAR(6), IN rating SMALLINT) LANGUAGE SQL BEGIN IF rating = 1 THEN UPDATE employee SET salary = salary * 1.10, bonus = 1500 WHERE empno = empNum; ELSE UPDATE employee SET salary = salary * 1.05, bonus = 1000 WHERE empno = empNum; END IF; END 2 Podstawowa struktura procedury Procedurę tworzy się przy użyciu polecenia CREATE PROCEDURE Najprostsza procedura: CREATE PROCEDURE proc01 () BEGIN END @ CREATE PROCEDURE nazwa ( <lista parametrów>) <właściwości procedury> <parametry kontrolne procedury> BEGIN ciało_procedury END CREATE PROCEDURE nazwa ( | IN | OUT | INOUT parametr typ) LANGUAGE SQL dla LUW nie trzeba [EXTERNAL ACTION | NO EXTERNAL ACTION] tylko dla LUW - wtedy, gdy akcja zmienia stan obiektu nie zarządzanego przez DB2 [SPECIFIC nazwa_specyfikacji czyli inaczej unikalna nazwa procedury] [DYNAMIC RESULT SETS liczba] [NOT DETERMINISTIC | DETERMINISTIC] [CALLED ON NULL INPUT] BEGIN ciało_procedury END Kiedy nazwa procedury nie jest kwalifikowana, schemat procedury jest wyznaczany na podstawie schematu bieżącego - czyli autoryzowanego identyfikatora bieżącego użytkownika. -3- IBM DB2 – Procedury składowane 4 Kwalifikowane nazwy - np. db2admin.reademp. Uwaga! Nie może to być schemat SYS! 2.1 Parametry Definicja parametrów składa się z 3 części: 1. trybu definiującego czy parametr jest WE (IN), WY (OUT), czy WE/WY (INOUT). Parametr w trybie INOUT pozwala przekazać wartość do wywoływanego podprogramu i zwrócić wartość na zewnątrz wywoływanego podprogramu. Wewnątrz programu taki parametr zachowuje się zainicjowana zmienna 2. nazwy parametru 3. SQL-owego typu i rozmiaru danych tego parametru CREATE PROCEDURE update_pensja (IN nr_prac INTEGER, IN procent_wzrostu DECIMAL(4,2), INOUT ilosc_prac INTEGER, OUT zaktualizowana_pensja DECIMAL(5,2)) Procedura może też nie mieć żadnych parametrów, a nawiasy mogą być wtedy pominięte. ... CREATE PROCEDURE update_pensja LANGUAGE SQL BEGIN ... lub: CREATE PROCEDURE update_pensja() LANGUAGE SQL BEGIN .. 2.1.1 Typy danych Mogą być typy 2 kategorii: − − wbudowane - Integer (Smallint, Bigint), Decimal (Numeric), Real (Double), Char, Varchar, CLOB (1bajtowe Character Large Object), GRAPHIC, DBCLOB (2-bajtowe Character Large Object), BLOB (Binary Large Objects), Date, Time, Timestamp, ROWID (iSeries) użytkownika - UDT (User-defined Data Types). Dla typów wbudowanych String można specyfikować podtypy - np. kolumny CHAR i VARCHAR mogą być definiowane jako FOR BIT DATA żeby przechowywać dane binarne. Do tworzenia typów UDT używa się: CREATE DISTINCT TYPE nazwa AS źródłowy_typ_danych WITH COMPARISIONS Klauzula WITH COMPARISIONS pozwala na użycie operatorów dostarczonych przez system dla źródłowych typów danych. Ta klauzula nie jest dozwolona dla typów źródłowych: BLOB, CLOB, DBCLOB,.. Niech przykładowo zdefiniowano 2 zmienne: DECLARE v_w_milach DOUBLE; DECLARE v_w_kilometrach DOUBLE; Chcę zapobiec wykoniu nieprawidłowej operacji typu: * IF (v_w_milach > v_w_kilometrach) - (nie mogę porównać bez konwersji) Mogę wobec tego stworzyć 2 typy: -4- IBM DB2 – Procedury składowane 5 CREATE DISTINCT TYPE mile AS DOUBLE WITH COMPARISIONS CREATE DISTINCT TYPE kilometry AS DOUBLE WITH COMPARISIONS Teraz mogę zadeklarować zmienne: DECLARE v_w_milach MILE; DECLARE v_w_kilometrach KILOMETRY; ... i teraz dostanę błąd SQL-owy jeżeli wykonam *. W momencie stworzenia UDT, DB2 generuje 2 funkcje rzutowania ???????: − − jedna rzutuje z UDt na typ źródłowy - MILE (DOUBLE) druga rzutuje na odwrót - DOUBLE (MILE). Podobnie się dzieje dla KILOMETRY. Tak więc, żeby zadziałało polecenie: IF (v_w_milach > 30.0) trzeba napisać: IF (v_w_milach > MILE (DOUBLE(v_w_kilometrach)/1,6)) IF (v_w_milach >MILE(30.0)) 2.2 Własności procedury Własności procedury to: język, liczba oczekiwanych zbiorów wynikowych, itd. Klauzula SPECIFIC jest ważna, kiedy wymagana jest definicja procedury o tej samej nazwie, ale z inną liczbą parametrów - tzw. przeładowanie - ale dotyczy to tylko iSeries i LUW (Linux, Unix i Windows). CREATE PROCEDURE suma (IN p_a INTEGER, IN p_b INTEGER, OUT p_s INTEGER) LANGUAGE SQL SPECIFIC suma_ab BEGIN SET p_s = p_a + p_b; END CREATE PROCEDURE suma (IN p_a INTEGER, IN p_b INTEGER, IN p_c INTEGER, OUT p_s INTEGER) LANGUAGE SQL SPECIFIC suma_abc BEGIN SET p_s = p_a + p_b + p_c; END Podczas wywołania procedury suma DB2 wyznacza wersję procedury na podstawie liczby parametrów. CALL suma(100, 200, ?) -5- IBM DB2 – Procedury składowane 6 Natomiast niedozwolone jest definiowanie procedur p tej samej nazwie z tą samą liczbą parametrów różnego typu. Co trzeba zrobić, żeby usunąć taką „przeładowaną” procedurę? − − wyspecyfikować parametry procedury w poleceniu DROP PROCEDURE np. DROP PROCEDURE suma(INTEGER, INTEGER, INTEGER) użyć DROP SPECIFIC PROCEDURE - np. DROP SPECIFIC PROCEDURE suma_ab Taka nazwa specyfikacji może też być użyta w zdaniu COMMENT ON np. COMMENT ON SPECIFIC PROCEDURE suma_abc IS ‘To jest 3-parametrowa wersja procedury’ W LUW jeżeli nazwa specyfikacji nie jest podana jawnie podczas tworzenia procedury, DB2 generuje unikalną nazwę składającą się z SQL i znacznika czasowego:SQLyymmddhhmmsshhn Klauzula DETERMINISTIC pozwala na określenie procedury, która zwraca te same wyniki dla każdego wywołania z identycznymi parametrami wejściowymi i ma służyć dalszej poprawie wydajności. Klauzula CALLED ON NULL INPUT oznacza, że procedura będzie zawsze wywoływana nawet, jeżeli jej parametry wejściowe będą NULL-ami. W opcji RESULT SETS podaje się maksymalną liczbę zbiorów wynikowych. 2.2.1 Otrzymywanie zbioru wynikowego Żeby zwrócić zbiór wynikowy do aplikacji wywołującej, procedura potrzebuje deklaracji kursora dla wybranych wierszy. Wiele zbiorów wynikowych może być zwróconych, ale każdy z nich wymaga niezależnego zdania DECLARE CURSOR. Przykład: CREATE PROCEDURE GetCusName() RESULT SETS 1 tu podaję max. liczbę zbiorów wyn. LANGUAGE SQL BEGIN DECLARE c1 CURSOR WITH RETURN FOR kursor użyto po to, aby zwrócić zbiór SELECT nazwisko FROM klient ORDER BY nazwisko OPEN c1; END DECLARE rs1 RESULT_SET_LOCATOR VARYING; CALL procedure1(); ASSOCIATE RESULT SET LOCATOR (rs1, rs2) WITH PROCEDURE procedure1; ALLOCATE cursor1 CURSOR FOR RESULT SET rs1; ALLOCATE cursor2 CURSOR FOR RESULT SET rs2; FETCH FROM cursor1 INTO var1, var2 ; FETCH FROM cursor2 INTO var3 ; Kursor jest zamykany przez program wywołujący po zwróceniu zbioru wynikowego. -6- IBM DB2 – Procedury składowane 2.3 7 Parametry kontrolne procedury, kontrolujące sposób tworzenia procedury Ustawia się je poleceniem SET OPTION. Do tych parametrów zalicza się: − DBGVIEW - generuje informacje do debugowania, − OUTPUT - wylistowuje wyjście, − TGTRLS - generuje kod dla OS/400. 2.4 Ciało procedury BEGIN DECLARE <deklaracja_zmiennych> DECLARE CURSOR <deklaracja_kursorów> <deklaracja_wyjątków> <zdania_SQL> END Dobrym zwyczajem jest wstawianie komentarzy: -- − poprzedzanych symbolami − otoczonych - jak w C - symbolami /* .... */ Zmienne muszą być deklarowane na początku bloku BEGIN/END przed jakimikolwiek zdaniami SQL. W przeciwnym wypadku wystąpi błąd. Zmienne muszą mieć nazwę różną od nazw kolumn tych tabel, do których odwołuje się procedura (ale błąd nie wystąpi). Najlepiej poprzedzać nazwy zmiennych v_ a nazwy parametrów p_. Po zadeklarowaniu zmiennych, są one inicjalizowane NULL-ami, chyba, że użyta zostanie klauzula DEFAULT inicjalizująca zmienną pewną wartością. DECLARE v_nr_prac VARCHAr(6); DECLARE v_total, v_liczba INTEGER DEFAULT 0; Można ustawić wartość pojedynczej zmiennej używając SET, lub poleceń SELECT i FETCH w kombinacji z INTO. Polecenie VALUES używane jest do wyliczenia wartości rejestru i związania z nią pewnej zmiennej. SET v_total = v_total + 1 SELECT max(pensja) INTO v_max FROM prac; VALUES CURRENT DATE INTO v_date; Przykład prostej procedury, aktualizującej zbiór nowym nazwiskiem klienta na podstawie numeru i nowego nazwiska klienta: CREATE PROCEDURE update_klient (IN nr CHARACTER(5), IN nazwisko CHARACTER(20)) LANGUAGE SQL UPDATE klient SET nazw_klienta = nazwisko WHERE nr_klienta = nr; -7- IBM DB2 – Procedury składowane 2.4.1 8 Rejestry W DB2 istnieją specjalne rejestry, będące rejestrami pamięciowymi pozwalającymi DB2 dostarczać aplikacji informacji o jej środowisku. Do tych rejestrów można się odwoływać w zdaniach SQL. modyfikowalneM niemodyfikowalne Najczęściej używa się następujących rejestrów: − − − − − − − − − − − CURRENT DATE - data na serwerze CURRENT TIME CURRENT TIMESTAMP CURRENT ISOLATION - poziom izolacji dla dynamicznego zdania SQL w ramach bieżącej sesji CURRENT LOCK TIMEOUT - liczba sekund, które aplikacja musi odczekać żeby uzyskać blokadę - można modyfikować M CURRENT PATH - można modyfikować M. Ścieżka jest listą schematów, które DB2 (kolejno!) przeszukuje żeby zlokalizować procedurę. Domyślną ścieżką w LUW jest: ‘SYSIBM’, ‘SYSFUN’, ‘SYSPROC’, ‘DB2ADMIN’ CURRENT PACKAGE PATH - M CURRENT SCHEMA - M nazwa schematu używana do kwalifikowania niekwalifikowanych obiektów bazodanowych. Można modyfikować przez SET CURRENT SCHEMA USER - ID autoryzacji używany do połączenia z bazą SESSION USER - ID autoryzacji używany dla bieżącego schematu - jest synonimem do rejestru USER SYSTEM USER - ID autoryzacji użytkownika połączonego z bazą. Żeby uzyskać wartość rejestru, należy użyć komendy SELECT, natomiast żeby zaktualizować modyfikowalny rejestr, należy użyć komendy SET. SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1; SET CURRENT SCHEMA = db2admin Oto przykład procedury tworzącej tabelę datetab w celu demonstracji użycia specjalnych rejestrów w SQL-u. CREATE PROCEDURE registersample (OUT p_start TIMESTAMP, OUT p_end TIMESTAMP, OUT p_c1 TIMESTAMP, OUT p_c2 TIME, OUT p_user CHAR(20)) LANGUAGE SQL SPECIFIC rejestrsample BEGIN CREATE TABLE datetab (c1 TIMESTAMP, c2 TIME, c3 DATE); VALUES CURRENT TIMESTAMP INTO p_start; INSERT INTO datetab VALUES (CURRENT TIMESTAMP, CURRENT TIME, CURRENT DATE + 3 DAYS); SELECT c1, c2 INTO p_c1, p_c2 FROM datetab; VALUES CURRENT TIMESTAMP INTO p_end; SET p_user = USER; DROP TABLE datetab; END 3 Wykonywanie procedur Uprawnienia, które musi mieć user: GRANT EXECUTE ON SPECIFIC PROCEDURE <nazwa procedury> TO USER <user> -8- IBM DB2 – Procedury składowane 9 Uprawnienia, które musi mieć developer: GRANT <operacje> ON <obiekty> TO USER <user> GRANT BINDADD ON <baza danych> TO USER <user> Polecenie CREATE PROCEDURE nie ma opcji “replace”, więc jeżeli chcę zastąpić istniejącą definicję procedury należy użyć DROP PROCEDURE. Procedurę wywołuje się poleceniem CALL, natomiast to polecenie wywołuje zewnętrzną procedurę: EXEC SQL CALL hsale (:param1, :param2, :param3, :param4) END-EXEC Utworzenie z okna komend: db2 –td@ -f simple.sql db2 call proc01() 3.1 Dynamiczny SQL W dynamicznym SQL-u polecenia są znane jedynie podczas wykonywania. Żeby pracować z dynamicznym SQL-em wykorzystuje się polecenia: − PREPARE – bierze zmienną VARCHAR zawierającą polecenie SQL i konwertuje je na polecenie wykonywalne − EXECUTE – pozwala wykonać poprzednio przygotowane polecenie PREPARE zdanie − EXECUTE IMMEDIATE – przygotowuje i wykonuje polecenie zawarte w stringu. Np. EXECUTE IMMEDIATE ‘UPDATE tabela SET ...’ DECLARE statement1 STATEMENT; SET string1 = ’UPDATE tab1 SET col1 = ? ’ || ’WHERE col2 = ?’ ; PREPARE statement1 FROM string1 ; EXECUTE statement1 USING var1,var2 3.1.1 Dynamiczny SQL - kursory DECLARE statement1 STATEMENT; DECLARE cursor1 CURSOR FOR statement1; SET string1 = ’SELECT column1 FROM tab1 ’ || ’WHERE column2 = ’ || CHAR( variable1) ; PREPARE statement1 FROM string1 ; OPEN cursor1; 3.2 Dynamiczny SQL - parametryzowanie -- Złóżmy, że sygnatura procedury wygląda: schema1.procedure1(IN,INOUT,OUT) -9- IBM DB2 – Procedury składowane 10 DECLARE statement1 STATEMENT; SET string1 = ’CALL schema1.procedure1’ || ’(?,?,?)’ ; PREPARE statement1 FROM string1 ; EXECUTE statement1 INTO var1,var2 USING var3,var4; USING VAR3 VAR4 CALL PROCEDURE1 ? ? ? definicja IN INOUT OUT VAR1 VAR2 INTO Elementy języka SQL PL 4 4.1 Sekwencje Sekwencje są obiektami, które pozwalają automatycznie generować wartości. CREATE SEQUENCE nazwa_sekwencji AS INTEGER | typ_danych START WITH wart_numeryczna INCREMENT BY wart_numeryczna MINVALUE wart_numeryczna MAXVALUE wart_numeryczna [NO CYCLE | CYCLE] Do generacji i uzyskania wartości sekwencji używane są wyrażenia: NEXT VALUE i PREVIOUS VALUE. VALUES PREVIOUS VALUE FOR sek1 INTO ... 4.2 1. Instrukcje sterujące pętle FOR, WHILE, LOOP, REPEAT pętla FOR nazwa pętli loop_name może być użyta do kwalifikowania zmiennych odnoszących się do wartości kolumn w związanym z FOR kursorze. Pętla ta jest używana tylko do przetwarzania wierszy tabel - tzn. przetwarzania każdego wiersza zwróconego przez podaną instrukcję SELECT. FOR loop_name AS SELECT kol1, kol2, … DO SET var1 = loop_name.col1; … END FOR; pętla WHILE WHILE (var1 = 1) DO … END WHILE; pętla LOOP - 10 - IBM DB2 – Procedury składowane 2. może być zdefiniowana etykieta bloku LOOP. Wewnątrz pętli musi być wyspecyfikowana opcja LEAVE, żeby można było wyjść z pętli (ale mogę też wyjść deklarując handler - zgłoszenie). Z kolei opcja ITERATE wymusza następną iterację w pętli. etykieta: LOOP … LEAVE etykieta; … ITERATE etykieta; END LOOP; pętla REPEAT REPEAT … UNTIL (var1 < 100) END REPEAT; “pętla” GOTO - GOTO zastępuje ITERATE. GOTO etykieta; RETURN int_value instrukcje warunkowe Dopuszcza się stosowanie trzech form instrukcji IF: IF-THEN, IF-THEN-ELSE, i IF-THEN-ELSEIF 4.3 11 IF v_var = 1 THEN UPDATE … ELSE INSERT … END IF; instrukcja CASE można ją użyć na 2 sposoby: CASE WHEN v_var = 0 THEN … WHEN v_var = 10 THEN … ELSE … END CASE; CASE v_var WHEN 0 THEN ... WHEN 10 THEN ... ELSE ... END CASE Kursory SQL PL niejawnie deklaruje kursor dla wszystkich instrukcji manipulowania danymi, włączając zapytania zwracające tylko jeden wiersz. Dla zapytań zwracających więcej niż jeden wiersz można jawnie zadeklarować kursor przetwarzający indywidualnie wiersze. - 11 - IBM DB2 – Procedury składowane 12 DECLARE SQLSTATE CHAR(5); DECLARE cursor1 CURSOR FOR select … ; -- Po deklaracji zmiennych OPEN cursor1; FETCH FROM cursor1 INTO var1, var2, … ; WHILE (SQLSTATE = ’00000’) DO … END WHILE; CLOSE cursor1; DB2 niejawnie otwiera kursor do przetwarzania każdej instrukcji SQL'a nie połączonej z jawnie zadeklarowanym kursorem. SQL PL pozwala odwoływać się do ostatniego niejawnego kursora jak do kursora SQL. Tym samym można używać atrybutów kursora w celu pozyskania informacji o ostatnio wykonanej instrukcji SQL. 4.3.1 Kursory FOR UPDATE Instrukcja OPEN wykonuje zapytanie skojarzone z jawnie zadeklarowanym kursorem. Otwarcie kursora wykonuje zapytanie i identyfikuje aktywny zbiór, który zawiera wiersze spełniające kryterium wyszukiwania. Dla kursorów zadeklarowanych z użyciem klauzuli FOR UPDATE, instrukcja OPEN blokuje te wiersze. DECLARE SQLSTATE CHAR(5); DECLARE cursor1 CURSOR FOR select … FOR UPDATE; -- domniemana wartość: FOR READ ONLY OPEN cursor1; FETCH FROM cursor1 INTO var1, var2, … ; WHILE (SQLSTATE = ’00000’) DO DELETE FROM tab1 WHERE CURRENT OF cursor1; … UPDATE tab1 SET … WHERE CURRENT OF cursor1; END WHILE; 4.3.2 Kursory WITH HOLD Te kursory są zachowywane po COMMIT. DECLARE cursor1 CURSOR WITH HOLD FOR select … FOR UPDATE; COMMIT; -- teraz kursory nie będą zamknięte ROLLBACK; -- wszystkie kursory są zamykane -- wszystkie blokady są zwalniane -- lokatory BLOB-ów są zwalniane 4.3.3 Kursory READ ONLY Nie będzie zakłądana blokada EXCLUSIVE LOCK - 12 - IBM DB2 – Procedury składowane 4.3.4 13 Kursory WITH RETURN Tylko dla aplikacji bazy z OS/390. Podstawowa obsługa błędów 4.4 W DB2 są następujące typy poleceń, zgłaszających błąd: 1. zmienne SQLCODE i SQLSTATE 2. deklaracje warunku i zgłoszenia (handlera) 3. polecenia SIGNAL i RESIGNAL 4. GET DIAGNOSTICS EXCEPTION 4.4.1 SQLCODE/SQLSTATE W DB2 są 2 zmienne, których DBMS używa do identyfikacji błędu: 1. 2. SQLSTATE - kod standaryzowany - niezależny od platformy. Ma 5 znaków, z czego 2 pierwsze reprezentują klasę błędu, a pozostałe 3 - szczegółowe warunki błędu (podklasę błędu). SQLCODE - tak DB2 raportuje błąd i ostrzeżenia - sposób oryginalny DB2. Jeżeli jest błąd, to SQLCODE jest < 0, SQLSTATE ≠ 00 | 01 | 02 Jeżeli jest ostrzeżenie, to SQLCODE jest > 0 i pierwsze 2 cyfry SQLSTATE = 01 | 02 Jeżeli jest wszystko w porządku, to SQLCODE = 0 i SQLSTATE = 00000 DECLARE SQLSTATE CHAR(5) DETAULT ’00000’;-- ISO/ANSI SQL92 -- ’00xxx’ – sukces -- ’01xxx’ – ostrzeżenie -- ’02xxx’ – not found -- other – błąd DECLARE SQLCODE INT DETAULT 0; -- DB2 specific -- 0 – sukces -- >0 – ostrzeżenie -- 100 – not found -- <0 – błąd Są też oczywiście błędy definiowane przez użytkownika. Np. pracownik nie może zarabiać więcej od swojego kierownika. Błędy te są kodowane w SQLSTATE przez pierwsze znaki ‘38’. 4.4.2 Deklaracja warunku i zgłoszenia CONDITION FOR Jakie są typowe sytuacje wymagające jawnego zgłoszenia błędu? − w SELECT-cie nie ma żadnych wierszy − nastąpiło naruszenie więzów integralności w poleceniu UPDATE lub DELETE − itd. Więc piszę: DECLARE record_not_found CONDITION FOR ;02000’ – record_not_found to nazwa warunku DECLARE check_constraint_error CONDITION FOR ‘23513’ Po słowie CONDITION FOR występuje wzięty numer z SQLSTATE. Wtedy deklarowany warunek wystąpi, gdy np. SQLSTATE = ‘23513’. - 13 - IBM DB2 – Procedury składowane 14 Żeby użyć nazwy warunku trzeba zadeklarować zgłoszenie, a potem – kiedy handler jest zdefiniowany/zadeklarowany – można podjąć jedną z 3 akcji: CONTINUE - sterowanie przechodzi do polecenia znajdującego się za tym poleceniem, które wywołało błąd. 2. EXIT - sterowanie jest przekazywane na koniec SQL złożonego 3. UNDO - wykonywana jest operacja rollback na złożonym SQL zaczynającym się od BEGIN ATOMIC. Przykład: 1. DECLARE not_found CONDITION FOR ‘02000’ DECLARE CONTINUE HANDLER FOR not_found SET at_end = 1 Poza predefiniowanymi w SQLSTATE handlerami można też definiować wyjątki w następujących sytuacjach: − SQLEXCEPTION − SQLWARNINGS − NOT FOUND Oto przykład typowego bloku poleceń na początku procedury: DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET v_sqlcode = SQLCODE; DECLARE UNDO HANDLER FOR SQLWARNING SET v_sqlcode = SQLCODE; DECLARE EXIT HANDLER FOR NOT FOUND SET v_sqlcode = SQLCODE; Ogólna postać: DECLARE condition-name CONDITION FOR SQLSTATE ’xxxxx’ ; Przykład: DECLARE not_found CONDITION FOR SQLSTATE ’02000’ ; 4.4.3 SIGNAL/RESIGNAL SIGNAL jawnie sygnalizuje warunek błędu/ostrzeżenia. Jeżeli jest definiowane zgłoszenie żeby zgłosić wyjątek, jest to wywoływane natychmiast przez polecenie SIGNAL. Sterowanie przechodzi wtedy do zdefiniowanego zgłoszenia błędu. Przykład: SIGNAL SQLSTATE ‘38001’ – zgłoszenie będzie uruchomione Polecenie RESIGNAL zwraca SQLSTATE i SQL MESSAGE TEXT do wywołującej zgłoszenie aplikacji. To polecenie ustawia wiadomość diagnozującą. Przykład: RESIGNAL SQLSTATE ‘38TNF’ SET MESSAGE TEXT = ‘nie znaleziono pracownika’ Przykład zaawansowanej obsługi: DECLARE EXIT HANDLER FOR SQLSTATE = ‘xxxxx’ RESIGNAL SQLSTATE ‘xxxxx’ SET MESSAGE TEXT = ‘.....’ Ostatni przykład: SIGNAL SQLSTATE ’xxxxx’; --------------------------------------------DECLARE condition1 CONDITION FOR SQLSTATE ’99001’; - 14 - IBM DB2 – Procedury składowane 15 IF (pojawił się błąd) THEN SIGNAL condition1 SET MESSAGE_TEXT = Twój komunikat błędu’; 4.4.4 GET DIAGNOSTICS GET DIAGNOSTICS EXCEPTION jest używany w celu umożliwienia dostępu do informacji związanej z błędem/ostzreżeniem. Samo GET DIAGNOSTICS może też być użyte do pozyskania informacji o liczbie wierszy przetworzonych przez instrukcje: INSERT, UPDATE, DELETE. Przykład: GET DIAGNOSTICS num_record = ROW_COUNT 4.5 Złożony SQL Złożony SQL pozwala grupować wiele poleceń (zwykle INSERT, UPDATE i DELETE) w jeden wykonywalny blok. Taki blok poleceń może być wykonany jako pojedynczy strumień, co redukuje czas wykonania i ruch w sieci. Złożony SQL nie gwarantuje porządku wykonania poleceń składowych, tak więc należy unikać wzajemnych zależności między poleceniami. Ogólna struktura zdania złożonego: etykieta: BEGIN <lista lokalnych deklaracji zmiennych> < lista lokalnych deklaracji kursora> <lista lokalnych deklaracji zgłoszeń - handlerów> <polecenia SQL> END; jak widać można etykietować: lab1: BEGIN DECLARE v_id INT; lab2: BEGIN DECLARE v_id INT; SET lab1.v_id = 1; SET lab2.v_id = 10; SET v_id = 100; END lab2; END lab1 BEGIN ATOMIC DECLARE v_var2 INTEGER; CREATE TABLE mytab(id INT); CREATE INDEX mytab_idx ON mytab(id); BEGIN DECLARE v_var4 INTEGER DEFAULT 100; INSERT INTO mytab(id) VALUES (99),(v_var4); GET DIAGNOSTICS v_var2 = ROW_COUNT; SET p_result = 'Number of rows: ' || char(v_var2); END; -- średnik jest wymagany END - 15 - IBM DB2 – Procedury składowane 16 BEGIN ATOMIC … -- SQL’e traktowane są jak jedno polecenie. Nie mogę tu użyć COMMIT i ROLLBACK END; -- nieobsłużony błąd -> zatrzymanie procedury. ->-- wszystkie zmiany są anulowane --------------------------------------------BEGIN NOT ATOMIC -- to jest domniemana wart. … COMMIT; ROLLBACK; ROLLBACK TO SAVEPOINT sp1; … END; -- nieobsłużony błąd -> zatrzymanie procedury ->-- Zmiany pozostają. Ręczne wycofanie lub zatwierdzenie 5 5.1 Procedury External Stored Procedures Zewnętrzna procedura składowana jest pisana przez użytkownika w jednym z języków programowania C, COBOL, RPG, FORTRAN, JAVA, C++, REXX, ... na serwerze iSeries. Żeby stworzyć zewnętrzną procedurę, kod źródłowy dla języka hosta musi być skompilowany, tak więc tworzony jest obiekt program. Wtedy używane jest polecenie CREATE PROCEDURE, które podpowiada systemowi gdzie znajduje się obiekt program, który implementuje tą procedurę. Czyli najpierw - przed użyciem zewnętrznej procedury - musi być ona zarejestrowana w bazie, np. przez CREATE PROCEDURE. Np. procedura zwracająca nazwisko dostawcy, który miesięcznie i rocznie sprzedaje najwięcej produktów. EXEC SQL CREATE PROCEDURE hsale (IN rok INTEGER, IN miesiąc INTEGER, OUT nazwisko_dostawcy CHAR(20), OUT hsale DECIMAL(11,2)) EXTERNAL NAME sproclib.hsales LANGUAGE RPGLE PARAMETER STYLE GENERAL END_EXEC 5.2 Procedury rejestrowe (registering stored procedures) Czym się różni polecenie CREATE PROCEDURE od DECLARE PROCEDURE? W CREATE procedura i definicje parametrów dodawane są do systemowych tabel katalogu - SYSROUTINES, i SYSPARMS (1 wiersz na 1 parametr). Jest też tabela SYSPROC. Tak więc procedura zaczyna być dostępna dla jakiegokolwiek programu klienckiego chodzącego na lokalnym lub zdalnym systemie. Czyli CREATE PROCEDURE potrzebuje być wykonane tylko raz w swoim życiu. Natomiast DECLARE jest głównie używane do tymczasowej rejestracji procedury w programie. SELECT * FROM QSYS2.SYSROUTINES; - 16 - IBM DB2 – Procedury składowane 17 SQL – PSM (rozszerzenia persistent stored module) - Język skryptowy do deklaracji i zarządzania procedurami 6 SQL PSM może być użyty w: 6.1 Procedurach składowanych, które są wywoływane poleceniem CALL. Triggerach – automatycznie wywoływanych kiedy zajdzie zdarzenie aktywujące. Funkcjach definiowanych przez użytkownika. Kompilacja procedury Skompilowany kod oraz opcjonalnie kod źródłowy procedury przechowany jest w katalogach systemowych. Jednocześnie tworzony jest pakiet, w którym przechowywane są plany wykonania statycznych poleceń SQL. CREATE PROCEDURE OUT_MEDIAN ( OUT medianSalary DOUBLE, OUT maxSalary DOUBLE) DYNAMIC RESULT SETS 0 LANGUAGE SQL MODIFIES SQL DATA BEGIN Parsing and compilation SQL PL pseudo code DECLARE v_numRecords INT DEFAULT 1 ; DECLARE v_salary1 DOUBLE DEFAULT 0 ; DECLARE c1 CURSOR FOR SELECT CAST(salary AS DOUBLE) FROM staff ORDER BY salary; 6.2 Procedure text Package DB2 System Catalogs Etapy wdrażania procedur -- REBIND – powtórne przygotowanie planów -- zapytań statycznych SQL-i CALL SYSPROC.REBIND_ROUTINE_PACKAGE ('P', 'MYSCHEMA.MYPROC', 'CONSERVATIVE') -- Przeniesienie skompilowanego kodu -- procedury do pliku GET ROUTINE INTO file1 FROM SPECIFIC PROCEDURE proc1 HIDE BODY ; -- Wgranie skompilowanej procedury do bazy: PUT ROUTINE FROM file1 ; 6.3 Opcje kompilacji i reoptymalizacji db2set DB2_SQLROUTINE_PREPOPTS= BLOCKING {UNAMBIG | ALL | NO} DATETIME {DEF | USA | EUR | ISO | JIS | LOC} DEGREE {1 | degree-of-parallelism | ANY} - 17 - IBM DB2 – Procedury składowane 18 DYNAMICRULES {BIND | RUN} EXPLAIN {NO | YES | ALL} EXPLSNAP {NO | YES | ALL} FEDERATED {NO | YES} INSERT {DEF | BUF} ISOLATION {CS |RR |UR |RS |NC} QUERYOPT optimization-level VALIDATE {RUN | BIND} -- na poziomie instancji; -- wymagany db2stop,db2start VALUES GET_ROUTINE_OPTS() ; -- bieżące parametry kompilacji CALL SET_ROUTINE_OPTS ('VALIDATE RUN ISOLATION UR') ; -- ustawienie dla bieżącej sesji CALL SET_ROUTINE_OPTS(NULL) -- przywrócenie domniemanych ustawień 7 Koncepcja nazywania procedur xxxxLEP L- język E - środowisko: N - Windows 4 - AS/400 M - OS/390 P - cel: C - klient S - procedura SQL 8 UDF Wyróżniamy 2 rodzaje: 4. 5. funkcje skalarne - zwracają pojedynczą, skalarną wartość; mogą być typu: − źródłowe - zarejestrowane w bazie, odwołujące się do innej funkcji − SQL - napisane w SQL − zewnętrzne - napisane w pewnym języku wysokiego poziomu funkcje tabel CREATE FUNCTION nazwa <deklaracja parametrów> RETURNS SPECIFIC LANGUAGE BEGIN <ciało funkcji> RETURN END - 18 -