Plan wykładu BAZY DANYCH II WYKŁAD 3 Zasięg zmiennych Zmienne powiązane Instrukcje warunkowe Pętle Pobieranie danych SQL w PL/SQL Rekordy dr inż. Agnieszka Bołtuć Zasięg zmiennych Zmienna jest dostępna tylko w bloku, w którym jest zadeklarowana, Kiedy zmienna wychodzi z zasięgu, system zwalnia i pamięć i takiej zmiennej nie można używać, Zmienna z bloku zagnieżdżonego jest niewidoczna w bloku zewnętrznym, Zmienna zadeklarowana w bloku zewnętrznym jest widoczna w bloku zagnieżdżonym. Zasięg zmiennych v_nazwa VARCHAR2(20); v_druga_nazwa VARCHAR2(20); v_druga_nazwa dostępna jest w bloku zagnieżdżonym v_nazwa dostępna jest w całym bloku 1
Widoczność zmiennych Gdy mam dwie zmienne o tych samych nazwach zadeklarowane w bloku zewnętrznym i zagnieżdżonym to zmienna ta jest ukryta w bloku wewnętrznym, Można to rozwiązać używając etykiet. Widoczność zmiennych v_nazwa VARCHAR2(20); v_nazwa VARCHAR2(20); Etykiety Zmienne powiązane <<l_zewnetrzna>> v_nazwa VARCHAR2(20); v_nazwa NUMBER(2); l_zewnetrzna.v_nazwa:= blok_zew ; DBMS_OUTPUT.PUT_LINE(l_zewnetrzna.v_nazwa); tzw. zmienne środowiskowe, podobne własności do zmiennych globalnych, Widoczne i dostępne w wielu programach, Często używane są do przekazywania wartości z PL/SQL do SQL, do optymalizacji zapytań, W PL/SQL zachowują się jak zwykłe zmienne. 2
Zmienne powiązane Zmienne powiązane - przykład deklaracja VARIABLE nazwa typ_danych; odwołanie do zmiennej :nazwa wyświetlenie zawartości zmiennej PRINT nazwa; VARIABLE v_imie VARCHAR2(20); SELECT first_name INTO :v_imie FROM employees WHERE employee_id=200; / PRINT v_imie; Zmienne powiązane - przykład Zmienne powiązane - przykład VARIABLE v_imie VARCHAR2(20); :v_imie := LEX ; / PRINT v_imie; SELECT last_name FROM employees WHERE first_name= :v_imie; VARIABLE v_imie VARCHAR2(20); SET AUTOPRINT ON; :v_imie := LEX ; / automatyczne włączenie wyświetlania zmiennych powiązanych SELECT last_name FROM employees WHERE first_name= :v_imie; 3
Struktury sterujące IF-THEN Wykonywanie warunkowe Wykonywanie w pętli Nawigacja sekwencyjna IF warunek THEN operacje; v_wiek NUMBER := 19; IF v_wiek>=18 THEN DBMS_OUTPUT.PUT_LINE( Jesteś pełnoletni ); IF-THEN-ELSE IF-THEN-ELSE IF warunek THEN operacje; [ELSE operacje;] v_wiek NUMBER := 19; IF v_wiek>=18 THEN DBMS_OUTPUT.PUT_LINE( Jesteś pełnoletni ); ELSE DBMS_OUTPUT.PUT_LINE( Nie jesteś pełnoletni ); 4
IF-THEN-ELSEIF IF-THEN-ELSEIF IF warunek THEN operacje; [ELSIF warunek THEN operacje;] [ELSE operacje;] v_wiek NUMBER := 19; IF v_wiek<18 THEN DBMS_OUTPUT.PUT_LINE( Nie jesteś pełnoletni ); ELSIF v_wiek<40 THEN DBMS_OUTPUT.PUT_LINE( Nie jesteś w średnim wieku ); ELSE DBMS_OUTPUT.PUT_LINE( Jesteś stary ); NULL w instrukcji IF v_wiek NUMBER; IF v_wiek>=18 THEN DBMS_OUTPUT.PUT_LINE( Jesteś pełnoletni ); Jeśli wyrażenie IF zwraca NULL to sterowanie jest przekazywane do ELSE CASE Od wersji 9i, Alternatywa warunkowego wykonywania kodu, upraszczająca składnię, CASE warunek WHEN test1 THEN operacje; WHEN test1 THEN operacje; [ELSE operacje;] END CASE; 5
CASE CASE z wyszukiwaniem v_ocena VARCHAR2(1); v_ocena_konw NUMBER(1); SELECT ocena INTO v_ocena FROM uczen WHERE przedmiot= algebra and id= 11234 ; CASE v_ocena WHEN A THEN v_ocena_konw:=5; WHEN B THEN v_ocena_konw:=4; ELSE v_ocena_konw:=0; END CASE; W takiej konstrukcji nie trzeba przekazywać wyrażenia na początku instrukcji CASE, Każda klauzula WHEN przyjmuje wyrażenie, którego wartość trzeba sprawdzić, Można podawać albo to samo wyrażenie w każdej klauzuli WHEN, lub za każdym razem inne. CASE z wyszukiwaniem Wykonywanie w pętli CASE WHEN v_dochod<85000 THEN v_podatek:=dochod*0.18; WHEN v_dochod>=85000 THEN v_podatek:=85000*0.18+(v_dochod-85000)*0.32; ELSE DBMS_OUTPUT.PUT_LINE( Brak dochodu ); END CASE; Pętle proste Pętle liczbowe FOR Pętle WHILE 6
Pętle proste Pętle proste LOOP operacje; EXIT [WHEN warunek]; v_licznik PLS_INTEGER :=1; LOOP DBMS_OUTPUT.PUT_LINE( Wiersz numer v_licznik); v_licznik:=v_licznik+1; EXIT WHEN v_licznik=10; Pętla FOR Pętla FOR FOR licznik IN [REVERSE] liczba_porzadkowa..liczba_koncowa LOOP operacje; FOR v_licznik IN 1..9 LOOP DBMS_OUTPUT.PUT_LINE( Wiersz numer v_licznik); 7
Pętla WHILE Pętla WHILE WHILE warunek LOOP operacje; v_licznik PLS_INTEGER :=1; WHILE v_licznik<10 LOOP DBMS_OUTPUT.PUT_LINE( Wiersz numer v_licznik); v_licznik:=v_licznik+1; Pętle i etykiety Pętle i etykiety Umożliwiają korzystanie z pętli tak, jakby miały nazwę, Nazywają nienazwane elementy języka PL/SQL, Wówczas możemy używać konstrukcji typu: EXIT nazwa_petli; EXIT nazwa_petli WHEN v_licznik=10; <<nazwa_petli>> pętla, instrukcje END LOOP nazwa_petli; opcjonalne 8
CONTINUE SQL w PL/SQL Dodatkowe sterownie pętlą, Przekazuje sterowanie do następnej iteracji, Od wersji 11g, Można używać w połączeniu z etykietami. FOR i IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE( i ); CONTINUE WHEN i> 5 ; DBMS_OUTPUT.PUT_LINE( tylko mniejsze, rowne 5 ); PL/SQL nie wspiera bezpośrednio poleceń DDL i DCL, w tym celu należy używać dynamicznego SQL, PL/SQL wspiera także polecenia z zakresu obsługi transakcji, Do pobierania danych służy polecenie SELECT. Polecenie SELECT SELECT lista_wyboru [INTO lista_zmiennych] FROM lista_tabel [WHERE warunki] [ORDER BY lista_kolumn]; Polecenie SELECT Lista_wyboru kolumny, łańcuchy, funkcje SQL, *, operacje arytmetyczne, Lista_zmiennych zmienna lub grupa zmiennych odpowiadających wartościom z listy wyboru, typy skalarne, zakotwiczone lub rekordy, Lista_tabel tabele, widoki, Pobrane wartości muszą trafić do zmiennej za pomocą INTO, Polecenie musi zwracać pojedynczy wiersz. 9
Polecenie SELECT Polecenie SELECT v_salary employees.salary%type; v_last_name employees.last_name%type; SELECT last_name, salary INTO v_last_name, v_salary FROM employees WHERE employees_id=105; DBMS_OUTPUT.PUT_LINE( Pracownik v_last_name); DBMS_OUTPUT.PUT_LINE( Zarabia v_salary); v_salary employees.salary%type; v_jobs employees.job_id%type := IT_PROG ; SELECT AVG(salary) INTO v_salary FROM employees WHERE job_id=v_jobs; DBMS_OUTPUT.PUT_LINE( Na stanowisku v_jobs); DBMS_OUTPUT.PUT_LINE( Średnia płaca wynosi v_salary); Rekordy Rekordy Zbiór zmiennych różnych typów, Wprowadzone w bazie danych Oracle 7, Typami pól rekordu mogą być wszystkie typy danych dostępne w Oracle, zdefiniowane przez użytkownika oraz kolekcje, Bardzo często zawartość rekordów jest wzorowana na strukturze tabel z bazy danych, Może mieć dowolną liczbę pól, Pola mogą mieć zainicjowaną wartość oraz być zdefiniowane jako NOT NULL, Są definiowane w części deklaracyjnej bloków, funkcji czy procedur, Mogą być zagnieżdżone, Definiowane za pomocą atrybutu %ROWTYPE lub jawnie. 10
%ROWTYPE Powoduje dziedziczenie definicji wierszy po kursorach, tabelach, obiektach lub widokach, Nazwy i typy pól rekordu są tworzone na podstawie wskazanego wiersza, identyfikator tabela%rowtype; v_employee employees%rowtype; v_jobs jobs%rowtype; Definicja jawna Definiowanie typu rekordowego TYPE nazwa_rec IS RECORD (deklaracja_pola [,deklaracja_pola] ); Definiowanie zmiennej typu rekordowego Identyfikator nazwa_rec; Deklaracja pola nazwa_pola {typ tabela.kolumna%type tabela%rowtype} [[NOT NULL] { := DEFAULT } wyrażenie] Deklaracja jawna TYPE r_emp IS RECORD (v_numer NUMBER(2), v_pensja NUMBER(8) :=1000, v_zatrudnienie employees.hire_date%type, v_spis jobs%rowtype); v_my_rec r_emp; Inicjowanie wartości pól v_my_rec.v_pensja:=v_my_rec.v_pensja+200; v_my_rec.v_zatrudnienie:=sysdate; v_my_rec.v_numer:=1; SELECT * INTO v_my_rec.v_spis FROM employees WHERE employee_id=105; DBMS_OUTPUT.PUT_LINE(v_my_rec.v_numer v_my_rec.v_spis.last_name TO_CHAR(v_my_rec.v_zatrudnienie TO_CHAR(v_my_rec.v_pensja) ); 11
Zagnieżdżanie Do tworzenia złożonych typów rekordowych można używać tylko jawnej definicji, Nie ma ograniczeń w zagnieżdżaniu, jeśli chodzi o poziomy, Wstawianie rekordu do tabeli v_rec employees%rowtype; SELECT * INTO v_rec FROM employees WHERE employee_id=105; INSERT INTO new_employees VALUES (v_rec.employee_id, v_rec.first_name, v_rec.last_name, ); Wstawianie rekordu do tabeli v_rec employees%rowtype; SELECT * INTO v_rec FROM employees WHERE employee_id=105; INSERT INTO new_employees VALUES v_rec; Modyfikacja za pomocą rekordów v_rec employees%rowtype; v_hire_date employees.hire_date%type; SELECT * INTO v_rec FROM employees WHERE employee_id=105; v_rec.hire_date:=sysdate; UPDATE employees SET ROW = v_rec WHERE employee_id=105; 12
Wykorzystana literatura J. Price, Oracle Database 11g i SQL. Programowanie. Helion, 2009. S. Urman, R. Hardman, M. McLaughlin, Oracle Database 10g. Programowanie w języku PL/SQL. Helion, 2008. www.oracle.com 13