Blok anonimowy
[
DECLARE
deklaracje zmiennych/stałych/wyjątków/kursorów/typów/procedur/funkcji
identyfikator typ_danych [NOT NULL] [:= wyrażenie];
identyfikator CONSTANT typ_danych [NOT NULL] [:= wyrażenie];
nazwa_wyjątku EXCEPTION; --RAISE nazwa_wyjątku
CURSOR nazwa_kursora IS instrukcja_SELECT; --(bez INTO)
jest typ BOOLEAN ze stałymi True i False
typ danych można pobrać z definicji tabeli nazwa_tabeli.nazwa_kolumny%TYPE
są też rekordy, np nazwa_tabeli%ROWTYPE
]
BEGIN
/*komentarz
...
*/
--komentarz do końca linii
ciąg instrukcji
z SQL mogą być SELECT, INSERT, UPDATE, DELETE, COMMIT i ROLLBACK
nie można pozostawić pustego ciągu, ale można null;
[
EXCEPTION
obsługa wyjątków
]
END;
w sqlplus . w osobnej linji żeby do bufora lub / żeby wykonać
Instrukcje sterujące
IF warunek THEN
ciąg_instrukcji
END IF;
IF warunek THEN
ciąg_instrukcji
ELSE
ciąg_instrukcji
END IF; --else dla False i Null
IF warunek THEN
ciąg_instrukcji
ELSIF warunek THEN
ciąg_instrukcji
END IF;
LOOP
ciąg_instrukcji (w tym EXIT lub EXIT WHEN warunek)
END LOOP;
FOR zmienna IN wartość1 .. wartość2 LOOP
null;
END LOOP;
WHILE warunek LOOP
null;
END LOOP;
Instrukcja select
SELECT wyrażenie, wyrażenie, ...
INTO zmienna, zmienna, ...
FROM tabela, tabela, ...
[WHERE ...][GROUP BY ...][HAVING ...][FOR UPDATE ...];
Musi zwracać dokładnie jeden wiersz wyników, np.
SELECT ename
INTO nazwisko
FROM emp
WHERE empno = 1030;
Zmienne systemowe
W PL/SQL (ale nie w SQL) można korzystać ze zmiennych systemowych.
SQL%ROWCOUNT - liczba wierszy przetworzonych przez ostatnią instrukcje SQL
SQL%FOUND - True jeżeli został przetworzony przynajmniej jeden wiersz
SQL%NOTFOUND - przeciwnie
oraz tylko w sekcji EXCEPTION
SQLERRM - tekstowa informacja o błędzie
SQLCODE - kod błędu
Komunikacja z użytkownikiem
Jest dostęp do zmiennych aplikacji korzystającej z bloku PL/SQL :nazwa_zmiennej.
Można też użyć zmienych podstawienia sqlplus &nazwa_zmiennej.
Do wypisywania na ekran można stosować DBMS_OUTPUT.Put_Line(napis) wcześniej ustawiając SET ServerOutput ON.
przykład 1
przykład 2
Wyjątki
W PL/SQL standardowe wyjątki mają przyporządkowane nazwy.
dup_val_on_index - ta sama wartość w indeksie jednoznacznym
no_data_found - zapytanie nie zwróciło wartość i dla zmiennych z klauzuli INTO
too_many_rows - zapytanie zwróciło więcej niż jeden wiersz dla zmiennych z klauzuli INTO
zero_divide - dzielenie przez zero
time_out_on_resource - zbyt długie oczekiwanie na zasoby
invalid cursor - niepoprawna operacja na kursorze
login_denied - niepoprawna nazwa użytkownika/hasło
invalid_number - błąd przy konwersji na liczbę
storage_error - zabrakło pamięci
cursor_already_open - kursor już otwarty
program error - błąd w interpreterze PL/SQL
Podstawowy przykład
przykład 1
Błędy występujace w sekcji DECLARE lub EXCEPTION są przekazywane na zewnątrz.
przykład 2
Do sprawdzenia która instrukcja spowodowaća błąd można używać podbloków z własną obsługą błędów
lub użyć licznika zwiększanego po wykonaniu każdej instrukcji.
Nowe wyjątki definiujemy w sekcji DECLARE za pomocą: nazwa_wyjątku EXCEPTION
Wyjątek można zgłosić przy pomocy: RAISE nazwa_wyjątku
przykład 3
Jest też procedura zgłaszająca wyjątek (wolno używać numerów od -20999 do -20000)
przykład 4
Można obsługiwać błędy przechwytywane przez serwer bazy danych
przykład 5
Kursory
CURSOR nazwa_kursora IS instrukcja_SELECT; --(bez INTO)
OPEN nazwa_kursora;
FETCH nazwa_kursora INTO zmienna, ...;
EXIT WHEN nazwa_kursora%NOTFOUND;
CLOSE nazwa_kursora;
przykład 1
Istnieje składnia skrócona.
przykład 2
Kursory można sparametryzować.
przykład 3
kursor%FOUND - czy z bazy sprowadzono kolejny wiersz
kursor%NOTFOUND - przeciwnie, już nie ma
kursor%ROWCOUNT - liczba sprowadzonych dotąd wierszy
kursor%ISOPEN - czy kursor jest otwarty
przykład 4
Jak przy SELECT można też blokować wiersze.
przykład 5
Można definiować typy kursorowe do przekazywania jako parametry procedur i funkcji.
przykład 6
Zmienna kursorowa jest jak wskaźnik (więc przekazujemy stan kursora). Nie można używać w kursorowym FOR.
Rekordy i tabele
Są rekordy (bardziej rekordowe niż typ wierszowy)
przykład 1
W algorytmach i do komunikacji aplikacji (szczególnie WWW) z bazą służą tabele.
Mogą przechowywać nieograniczoną liczbę wierszy i są indeksowane (niekoniecznie kolejnymi) liczbami całkowitymi BINARY_INTEGER.
przykład 2
tab.EXISTS(i) - czy i-ty element jest określony
tab.COUNT - liczba elementów w tabeli
tab.FIRST - pierwszy element w tabeli
tab.LAST - ostatni element w tabeli
tab.PRIOR(i) - element poprzedzający i-ty
tab.NEXT(i) - element następujący po i-tym
tab.DELETE - usuń wszystkie elementy
tab.DELETE(i) - usuń i-ty element
tab.DELETE(i,j) - usuń elementy od i-tego do j-tego
przykład 3
Procedury i funkcje
CREATE [OR REPLACE]
PROCEDURE nazwa(lista_parametrow) {AS|IS}
blok PL/SQL bez słowa DECLARE (ale to co pomiedzy DECLARE i BEGIN moze byc)
Typy przekazywania parametrów: IN, OUT, IN OUT (domyślny).
Nie podajemy rozmiaru, czyli np. tylko VARCHAR2 (nadal można tab.kol%TYPE)
przykład 1
Błędy przy kompilacji można obejrzeć dzięki show errors
CALL nazwa(param) - z SQL
EXECUTE nazwa(param) - z sqlplus
nazwa(param) - z kodu PL/SQL
CREATE [OR REPLACE]
FUNCTION nazwa(lista_parametrow)
RETURN typ_danych {IS|AS}
blok PL/SQL bez słowa DECLARE (ale to co pomiedzy DECLARE i BEGIN moze byc)
blok musi zawierac: RETURN wartosc;
przykład 2
SELECT nazwa(parma) FROM tab; - z SQL
VARIABLE x INETGER; EXECUTE :x := nazwa(parma) - z sqlplus
x := nazwa(parma) - z kodu PL/SQL
Można podawać wartości domyślne parametrów po słowie kluczowym DEFAULT.
Parametry w wartościami domyślnymi muszą był na końcu.
Jak kilka to wywołujemy: fun(par1,par2, nazwa_par4 => par4)
przykład 3
Funkcji można używać w instrukcjach SQL tak jak funkcji standardowych, ale nie mogą
modyfikować stanu bazy, ani nie mogą mieć parametrów wyjściowych. Nie powinny korzystać ze zmiennych
nielokalnych zadeklarowanych w pakietach, ani z notacji: nazwa_param => wartosc.
przykład 4
Żeby zobaczyć informację o parametrach procedury lub funkcji piszemy: DESC[RIBE] nazwa
Można też skorzystać z perspektywy słownikowej user_source
przykład 5
Procedury i funkcje można przeciążać.
Pakiety
Pakiet składa się z części publicznej (specyfikacja) i prywatnej (implementacja). Każda sesja ma
swój egzemplaż pakietu, czyli zmienne zachowują swoje wartości na czas trwania sesji.
CREATE [OR REPLACE] PACKAGE nazwa_pakietu AS
definicje obiektów publicznych (dla procedur i funkcji tylko nagłówki)
END nazwa_pakietu;
CREATE [OR REPLACE] PACKAGE BODY nazwa_pakietu AS
definicje obiektów publicznych i prywatnych
[
BEGIN
instrukcje inicjalizujące
]
END nazwa_pakietu;
Nie można przekazywać kursora przez parametr procedury, ani współdzielić zmiennych kursorowych.
Definiując funkcje należy zamieszczać dyrektywę kompilatora: PRAGMA RESTRICT_REFERENCES(nazwa_funkcji, opcja, ...), gdzie:
WNDS - funkcja nie modyfikuje bazy danych
WNPS - funkcja nie modyfikuje zmiennych pakietu
RNDS - funkcja nie odczytuje zawartości bazy danych
RNPS - funkcja nie odczytuje zmiennych pakietu
Sekwencje
CREATE SEQUENCE nazwa_sekw
[INCREMENT BY k]
[START WITH n];
DROP SEQUENCE nazwa_sekw
Odwołujemy się przy pomocy nazwa_sekw.NextVal oraz nazwa_sekw.CurrVal