Programowanie serwera
Oracle 11g SQL i PL/SQL
Autor: Adam Pelikant
ISBN: 978-83-246-2429-4
Format: 158u235, stron: 336
Twórz przejrzyste bazy danych i w³aœciwie przetwarzaj informacje
• Podstawy – organizacja serwera, instalacja bazy danych i koñcówki klienta
• Jêzyk SQL – tworzenie ró¿nych rodzajów zapytañ, funkcjonalnoœci dodatkowe
• Jêzyk PL/SQL – procedury, funkcje, dynamiczny SQL
Bazy danych Oracle od lat stanowi¹ najlepsz¹ alternatywê dla wszystkich tych, którzy
potrzebuj¹ funkcjonalnych i pojemnych struktur przechowywania danych,
wyposa¿onych dodatkowo w mo¿liwoœæ wszechstronnego przeszukiwania i zestawiania
potrzebnych informacji. Jednak podstawowa wiedza na temat œrodowiska Oracle nie
wystarczy, aby zaprojektowaæ naprawdê przejrzyst¹, prost¹ w obs³udze bazê. Do tego
potrzebna jest solidna wiedza, któr¹ znajdziesz w³aœnie w tym podrêczniku.
„Programowanie serwera Oracle 11g SQL i PL/SQL” to kontynuacja ksi¹¿ki Adama
Pelikanta „Bazy danych. Pierwsze starcie”, a poruszane w niej zagadnienia s¹ bardziej
zaawansowane, choæ przy odrobinie samozaparcia tak¿e nowicjusz w tej dziedzinie
bêdzie w stanie przyswoiæ sobie zawart¹ tu praktyczn¹ wiedzê. Oprócz organizacji
serwera, instalacji bazy danych i sk³adni jêzyka SQL szczegó³owo omówione s¹ tutaj
ró¿ne rodzaje zapytañ w tym jêzyku (prostych i z³o¿onych), a tak¿e funkcje rozszerzenia
proceduralnego PL/SQL. W ksi¹¿ce opisano tak¿e zastosowanie Javy do tworzenia
oprogramowania po stronie serwera oraz funkcje analityczne, stanowi¹ce wstêp do
przetwarzania OLAP. Ca³oœæ uzupe³niono praktycznymi przyk³adami, obrazuj¹cymi
dzia³anie poszczególnych konstrukcji i procedur.
• Organizacja serwera
• Instalacja bazy i koñcówki klienta
• Zapytania wybieraj¹ce, modyfikuj¹ce dane i tworz¹ce tabele
• Dodatkowe funkcjonalnoœci SQL
• Procedury sk³adowane i wyzwalane
• Funkcje w PL/SQL
• Pakiety, kursory, transakcje
• Dynamiczny SQL
• Zastosowanie Javy do tworzenia oprogramowania po stronie serwera
• Elementy administracji – zarz¹dzanie uprawnieniami z poziomu SQL
• Obiektowoœæ w Oracle
Wydajna, bezpieczna i prosta w obs³udze – zaprojektuj doskona³¹ bazê danych!
Spis treĈci
Od autora ......................................................................................... 5
CzöĈè I
Oracle SQL ..................................................................... 7
Rozdziaä 1. Wstöp .............................................................................................. 9
Organizacja serwera ....................................................................................................... 10
Instalacja bazy i koĔcówki klienta .................................................................................. 12
Rozdziaä 2. Zapytania wybierajñce ................................................................... 27
Podstawowe elementy skáadni ........................................................................................ 27
Grupowanie i funkcje agregujące ................................................................................... 36
Zapytania do wielu tabel — záączenia ............................................................................ 40
Grupowanie i funkcje analityczne .................................................................................. 49
Funkcje analityczne i rankingowe .................................................................................. 63
Pozostaáe elementy skáadniowe stosowane w SQL ........................................................ 87
Obsáuga grafów w SQL .................................................................................................. 94
Rozdziaä 3. Zapytania modyfikujñce dane ......................................................... 99
Rozdziaä 4. Zapytania tworzñce tabele ........................................................... 103
Zapytania modyfikujące tabelĊ ..................................................................................... 110
Dodatkowe informacje ................................................................................................. 114
Sekwencja ..................................................................................................................... 119
Perspektywy ................................................................................................................. 121
Indeksy ......................................................................................................................... 130
Rozdziaä 5. Dodatkowe funkcjonalnoĈci SQL ................................................... 137
Zapytania dla struktur XML ......................................................................................... 137
CzöĈè II ORACLE PL/SQL ........................................................ 153
Rozdziaä 6. PL/SQL ........................................................................................ 155
Podstawy skáadni .......................................................................................................... 155
Rozdziaä 7. Procedury skäadowane .................................................................. 163
Rozdziaä 8. Funkcje w PL/SQL ....................................................................... 179
Rozdziaä 9. Pakiety ........................................................................................ 187
4
Spis treĈci
Rozdziaä 10. Procedury wyzwalane ................................................................... 197
Rozdziaä 11. Kursory ........................................................................................ 229
Rozdziaä 12. Transakcje ................................................................................... 247
Rozdziaä 13. Dynamiczny SQL ........................................................................... 253
Rozdziaä 14. Zastosowanie Javy do tworzenia oprogramowania
po stronie serwera ....................................................................... 269
Rozdziaä 15. Elementy administracji
— zarzñdzanie uprawnieniami z poziomu SQL ................................. 289
Rozdziaä 16. ObiektowoĈè w Oracle .................................................................. 301
Zakoþczenie ................................................................................ 315
Skorowidz .................................................................................... 317
Rozdziaä 7.
Procedury skäadowane
Zamiast tworzy
ü
bloki anonimowe, wygodniej jest organizowa
ü
kod w nazwane pro-
cedury. W
Ğ
rodowisku baz danych nosz
ą
one miano procedur sk
á
adowanych. W przy-
padku j
Ċ
zyków wy
Ī
szego rz
Ċ
du taka organizacja kodu podyktowana jest ch
Ċ
ci
ą
utrzy-
mania jego przejrzysto
Ğ
ci — je
Ğ
li jego fragment ma by
ü
wykonywany wielokrotnie,
warto go umie
Ğ
ci
ü
w procedurze i odwo
á
ywa
ü
si
Ċ
do niego tylko przez jej wywo
á
ywanie.
Tak
Ī
e ró
Ī
ne funkcjonalno
Ğ
ci, zadania kodu s
ą
argumentem za jego podzia
á
em. Pod-
stawowa sk
á
adnia polecenia tworz
ą
cego procedur
Ċ
ma posta
ü
:
CREATE PROCEDURE nazwa
IS
BEGIN
-- ciaáo procedury
END;
Zamiast s
á
owa kluczowego
IS
mo
Ī
na stosowa
ü
to
Ī
same s
á
owo kluczowe
AS
. Cia
á
em
procedury mo
Ī
e by
ü
dowolny zestaw instrukcji PL/SQL oraz dowolne zapytania SQL,
za wyj
ą
tkiem zapytania wybieraj
ą
cego
SELECT
.
W przypadku
Ğ
rodowisk baz danych wydaje si
Ċ
jednak,
Ī
e argumenty zwi
ą
zane z or-
ganizacj
ą
kodu nie s
ą
tu najwa
Ī
niejsze. Dla procedur sk
á
adowanych najpó
Ĩ
niej przy
pierwszym ich wykonaniu generowany jest plan wykonania zapyta
Ĕ
wchodz
ą
cych w ich
sk
á
ad, ich kod jest wst
Ċ
pnie optymalizowany, a nast
Ċ
pnie s
ą
one prekompilowane. W ten
sposób na serwerze przechowywana jest procedura w dwóch postaciach: przepisu na
jej utworzenie
CREATE PROCEDURE
oraz skompilowanego kodu. Przy ka
Ī
dym nast
Ċ
pnym
wykonaniu odwo
á
ujemy si
Ċ
ju
Ī
do postaci skompilowanej. Sprawia to,
Ī
e procedury s
ą
wykonywane szybciej i wydajniej ni
Ī
ten sam kod w formie skryptu. Sprawa nie jest tak
oczywista w przypadku cz
Ċ
sto wykonywanych zapyta
Ĕ
. Plany wykonania ka
Ī
dego za-
pytania przechowywane s
ą
w pami
Ċ
ci wspó
á
dzielonej (
SGA
—
System Global Area
) i je-
Ī
eli wykonamy je ponownie, wykorzystana zostanie jego przetworzona posta
ü
. Nale
Ī
y
jednak pami
Ċ
ta
ü
,
Ī
e zgodno
Ğü
dwóch zapyta
Ĕ
sprawdzana jest z dok
á
adno
Ğ
ci
ą
do znaku,
nie jest natomiast analizowana semantyka. Poza tym informacje o planach zapyta
Ĕ
s
ą
nadpisywane na stare definicje w momencie wyczerpania zasobów pami
Ċ
ci wspó
á
dzie-
lonej. Bez wzgl
Ċ
du na te uwagi mo
Ī
emy jednak przyj
ąü
,
Ī
e wydajno
Ğü
przetwarzania
procedury sk
á
adowanej jest wi
Ċ
ksza ni
Ī
w przypadku równowa
Ī
nego jej skryptu (bloku
anonimowego). Je
Ī
eli chcemy usun
ąü
definicj
Ċ
procedury, mo
Ī
emy u
Ī
y
ü
nast
Ċ
puj
ą
cego
polecenia:
164
CzöĈè II i ORACLE PL/SQL
DROP PROCEDURE nazwa;
Wielokrotnie mo
Ī
emy chcie
ü
modyfikowa
ü
kod procedury. Ponowne wykonanie po-
lecenia
CREATE PROCEDURE
spowoduje wykrycie obiektu o tej samej nazwie i wy
Ğ
wie-
tlenie komunikatu o b
áĊ
dzie. W zwi
ą
zku z tym musimy najpierw usun
ąü
definicj
Ċ
pro-
cedury, a nast
Ċ
pnie utworzy
ü
j
ą
ponownie. Zamiast tego mo
Ī
emy pos
á
u
Ī
y
ü
si
Ċ
sk
á
adni
ą
CREATE OR REPLACE PROCEDURE
, która, w zale
Ī
no
Ğ
ci od tego, czy procedura o danej na-
zwie ju
Ī
istnieje, czy te
Ī
nie, stworzy j
ą
od podstaw lub nadpisze na istniej
ą
cej now
ą
definicj
Ċ
. Z punktu widzenia programisty nie da si
Ċ
rozró
Ī
ni
ü
, która z tych akcji zosta
á
a
wykonana (taki sam komunikat —
Procedura zostaáa pomyĞlnie utworzona
), dlatego,
korzystaj
ą
c z tej sk
á
adni, nale
Ī
y si
Ċ
upewni
ü
, czy nadpisujemy kod w
á
a
Ğ
ciwej proce-
dury! Przyk
á
adem mo
Ī
e by
ü
utworzenie procedury, której zadaniem b
Ċ
dzie zamiana
wszystkich nazwisk w tabeli
Osoby
na pisane du
Ī
ymi literami.
CREATE OR REPLACE PROCEDURE up
IS
BEGIN
UPDATE Osoby SET Nazwisko=UPPER(Nazwisko);
END;
Jak wida
ü
, cia
á
o procedury zawiera zapytanie aktualizuj
ą
ce
UPDATE
zgodne ze sk
á
adni
ą
SQL. Jej wywo
á
anie mo
Ī
e odby
ü
si
Ċ
na przyk
á
ad z wn
Ċ
trza bloku anonimowego o postaci:
BEGIN
up;
END;
Za
á
ó
Ī
my,
Ī
e w ramach tego samego skryptu chcieliby
Ğ
my sprawdzi
ü
poprawno
Ğü
wy-
konania procedury zapytaniem wybieraj
ą
cym
SELECT
. Zgodnie z wcze
Ğ
niejsz
ą
uwag
ą
,
zamieszczenie go w ciele bloku anonimowego jest niedozwolone. Równie
Ī
umiesz-
czenie zapytania wybieraj
ą
cego bezpo
Ğ
rednio po s
á
owie kluczowym
END;
zako
Ĕ
czy
si
Ċ
komunikatem o b
áĊ
dzie. St
ą
d konieczno
Ğü
podzielenia skryptu na dwie cz
ĊĞ
ci, które
z punktu widzenia serwera stanowi
ü
b
Ċ
d
ą
osobne fragmenty. Znakiem odpowiedzial-
nym za taki podzia
á
jest slash (
/
), przy czym cz
ĊĞ
ci b
Ċ
d
ą
traktowane jako fragmenty
kodu PL/SQL lub zapytania SQL, w zale
Ī
no
Ğ
ci od zawarto
Ğ
ci. Skrypt mo
Ī
e zosta
ü
podzielony w ten sposób na dowoln
ą
liczb
Ċ
niezale
Ī
nych fragmentów.
BEGIN
up;
END;
/
SELECT Nazwisko FROM Osoby;
Innym przyk
á
adem realizacji procedury sk
á
adowanej jest zastosowanie jej do przepi-
sywania nazwisk i wzrostu osób do tabeli
wys_tab
, przy czym rekordy posortowane
b
Ċ
d
ą
malej
ą
co wed
á
ug wzrostu. Nale
Ī
y zauwa
Ī
y
ü
,
Ī
e tabela
wys_tab
o odpowiedniej
strukturze musi ju
Ī
istnie
ü
w schemacie u
Ī
ytkownika.
CREATE OR REPLACE PROCEDURE wysocy
IS
BEGIN
INSERT INTO wys_tab(Nazwisko,Wzrost)
SELECT Nazwisko, Wzrost FROM Osoby
ORDER BY Wzrost DESC;
END wysocy;
Rozdziaä 7. i Procedury skäadowane
165
W przedstawionym przyk
á
adzie definicja tworzonej procedury jest ko
Ĕ
czona polece-
niem
END nazwa;
, gdzie
nazwa
jest jej nazw
ą
. Pomini
Ċ
cie jej w tym poleceniu nie po-
ci
ą
ga za sob
ą Ī
adnych zmian. Ko
Ĕ
czenie definicji procedury w prezentowany sposób
jest wskazane ze wzgl
Ċ
dów organizacyjnych, porz
ą
dkowych, zw
á
aszcza wtedy, kiedy
skrypt zawiera wi
Ċ
ksz
ą
liczb
Ċ
z
á
o
Ī
onych procedur, co utrudnia znalezienie ko
Ĕ
ców de-
finicji przy jego poprawianiu.
Dotychczas prezentowane przyk
á
ady by
á
y procedurami niepobieraj
ą
cymi
Ī
adnych da-
nych z wywo
á
uj
ą
cego je skryptu — by
á
y bezparametrowe. Brak parametrów wywo
á
a-
nia jest szczególnie widoczny w drugim przypadku, gdzie do tabeli
wys_tab
trafiaj
ą
wszyscy pracownicy — wszyscy s
ą
traktowani jako wysocy. Zmodyfikujmy t
Ċ
proce-
dur
Ċ
tak, aby do tabeli docelowej przepisywane by
á
y tylko osoby wy
Ī
sze od pewnego
progu danego w postaci parametru.
CREATE OR REPLACE PROCEDURE wysocy
(mm number)
IS
BEGIN
INSERT INTO wys_tab(Nazwisko,wzrost)
SELECT Nazwisko, wzrost FROM Osoby
WHERE wzrost > mm
ORDER BY wzrost DESC;
END wysocy;
Jak pokazano, parametry procedury definiowane s
ą
w nawiasie po jej nazwie, a na mi-
nimaln
ą
definicj
Ċ
sk
á
ada si
Ċ
nazwa i typ parametru, przy czym typ podawany jest bez
definiowania rozmiaru, czyli
number
, a nie
number(10)
. Podanie rozmiaru w tym miej-
scu powoduje wy
Ğ
wietlenie komunikatu o b
áĊ
dzie. Zdefiniowanie parametru procedury
sprawia,
Ī
e jest on traktowany tak jak zadeklarowana zmienna i nie mo
Ī
e zosta
ü
zade-
klarowany ponownie w jej ciele. Mo
Ī
e on zosta
ü
u
Ī
yty w dowolnym miejscu definicji
procedury; w przedstawionym przyk
á
adzie zosta
á
wykorzystany do sformu
á
owania wa-
runku w klauzuli
WHERE
zapytania wstawiaj
ą
cego wiersze.
Je
Ī
eli chcemy u
Ī
y
ü
w definicji procedury wi
Ċ
cej ni
Ī
jednego parametru, ich lista po-
winna by
ü
rozdzielona przecinkami. W przyk
á
adzie przedstawiono procedur
Ċ
, która
wstawia do tabeli
Dodatki
wiersze zawieraj
ą
ce sum
Ċ
warto
Ğ
ci brutto i sta
á
ej danej dru-
gim parametrem procedury
Dodatek
dla osoby, której identyfikator zawiera pierwszy
z parametrów
Num
.
CREATE OR REPLACE PROCEDURE Dodaj
(Num number, Dodatek number)
IS
BEGIN
INSERT INTO Dodatki
SELECT Brutto+Dodatek FROM Zarobki
WHERE IdOsoby = Num;
END;
Jak przedstawiono to w dotychczasowych przyk
á
adach, zawarto
Ğü
procedury mog
ą
sta-
nowi
ü
wszystkie zapytania modyfikuj
ą
ce dane, ale równie
Ī
zapytania tworz
ą
ce lub mo-
dyfikuj
ą
ce struktur
Ċ
bazy. Czasami jednak, zamiast wykonywa
ü
jakie
Ğ
operacje na da-
nych, chcemy dokona
ü
operacji zwracaj
ą
cej wynik w postaci zmiennej, np. policzy
ü
czy
166
CzöĈè II i ORACLE PL/SQL
podsumowa
ü
jak
ąĞ
wielko
Ğü
zapisan
ą
w bazie. W takim przypadku w ciele procedury
wykorzystujemy bardzo cz
Ċ
sto sk
á
adni
Ċ
SELECT ... INTO zmienna
. Powoduje ona,
Ī
e
wyznaczona zapytaniem warto
Ğü
skalarna jest przypisywana do zmiennej wyst
Ċ
puj
ą
-
cej po s
á
owie kluczowym
INTO
. Zapytanie takie nie skutkuje wyprowadzeniem danych
na standardowe wyj
Ğ
cie. Nie jest ono elementem SQL, a co za tym idzie, mo
Ī
e by
ü
u
Ī
ywane tylko we wn
Ċ
trzu procedur i funkcji albo w blokach anonimowych PL/SQL.
Je
Ī
eli dokonujemy takiego przypisania do zmiennej, która jest parametrem procedury,
to parametr taki musi mie
ü
sufiks
OUT
wskazuj
ą
cy,
Ī
e jest on przekazywany z proce-
dury do miejsca jej wywo
á
ania. Je
Ğ
li nie zdefiniujemy parametru jako „wychodz
ą
cego”,
to próba przypisania mu warto
Ğ
ci spowoduje pojawienie si
Ċ
komunikatu o b
áĊ
dzie.
Wszystkie parametry, które nie maj
ą
jawnie okre
Ğ
lonego kierunku przekazywania da-
nych, s
ą
domy
Ğ
lnie typu
IN
, czyli przekazuj
ą
dane tylko do procedury. Dopuszczalny
jest jeszcze trzeci przypadek, w którym zarówno zmienna przekazywana jest do pro-
cedury, jak i obliczona wewn
ą
trz procedury warto
Ğü
przekazywana jest na zewn
ą
trz.
W takiej sytuacji zmienna jest opisywana par
ą
IN OUT
. Prezentowana procedura zlicza
osoby wy
Ī
sze, ni
Ī
to okre
Ğ
la warto
Ğü
progowa dana pierwszym parametrem.
CREATE OR REPLACE PROCEDURE wysocy
(mm number, ile OUT number)
IS
BEGIN
SELECT COUNT(wzrost) INTO ile FROM Osoby
WHERE wzrost > mm;
END wysocy;
Wywo
á
anie tak zdefiniowanej procedury z bloku anonimowego wymaga zadeklaro-
wania zmiennej, do której zostanie przypisany parametr typu
OUT
. Musi ona mie
ü
typ
zgodny z parametrem formalnym, ale wymagane jest te
Ī
podanie jego rozmiaru, o ile
typ nie oferuje rozmiaru domy
Ğ
lnego. W prezentowanym przyk
á
adzie zadeklarowano
zmienn
ą
ile
jako
number
(bo domy
Ğ
lnie
number { number(10)
). W przypadku zmien-
nych znakowych rozmiar pola musi by
ü
dany jawnie (
varchar(11)
). Wywo
á
ania pro-
cedury dokonujemy przez podanie jej nazwy oraz zdefiniowanie warto
Ğ
ci parametrów
— czyli podanie listy parametrów aktualnych. Do parametrów typu
IN
mo
Ī
emy przy-
pisywa
ü
zarówno zmienne, jak i sta
á
e, natomiast do parametrów typu
OUT
musimy
przypisa
ü
zmienne. W prezentowanym przyk
á
adzie nazwa zmiennej oraz parametru
w definicji procedury jest taka sama, co jest powszechnie stosowan
ą
notacj
ą
, cho
ü
ze
wzgl
Ċ
dów sk
á
adniowych zgodno
Ğü
nazw nie jest wymagana.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(1.8, ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Oczywi
Ğ
cie procedura mo
Ī
e zawiera
ü
wi
Ċ
cej ni
Ī
jeden parametr typu
OUT
. Za
á
ó
Ī
my,
Ī
e oprócz liczby osób o wzro
Ğ
cie wi
Ċ
kszym od warto
Ğ
ci progowej chcemy wyznaczy
ü
ich
Ğ
redni wzrost. Mo
Ī
emy zastosowa
ü
dwa zapytania agreguj
ą
ce, które okre
Ğ
l
ą
intere-
suj
ą
ce nas warto
Ğ
ci, jednak bardziej wydajne jest u
Ī
ycie podwójnego przypisania w zapyta-
niu
SELECT ... INTO
. Je
Ğ
li zwraca ono jeden wiersz, to po s
á
owie kluczowym
INTO
mu-
simy umie
Ğ
ci
ü
tyle zmiennych, ile wyra
Ī
e
Ĕ
jest wyznaczanych w jego pierwszej cz
ĊĞ
ci.
Rozdziaä 7. i Procedury skäadowane
167
CREATE OR REPLACE PROCEDURE wysocy
(mm number, ile OUT number, sr OUT real)
IS
BEGIN
SELECT COUNT(wzrost), AVG(wzrost) INTO ile, sr FROM Osoby
WHERE wzrost > mm;
END wysocy;
Dla ka
Ī
dego parametru mo
Ī
e zosta
ü
zdefiniowana warto
Ğü
domy
Ğ
lna. Wykonujemy to
przez podanie po typie zmiennej s
á
owa kluczowego
DEFAULT
, po którym ustanawiana
jest warto
Ğü
. W prezentowanym przyk
á
adzie przyj
Ċ
to,
Ī
e domy
Ğ
ln
ą
warto
Ğ
ci
ą
progu,
od którego zliczamy osoby wysokie, jest
1.7
.
CREATE OR REPLACE PROCEDURE wysocy
(mm NUMBER DEFAULT 1.7, ile OUT NUMBER)
IS
BEGIN
SELECT COUNT(wzrost) INTO ile FROM Osoby
WHERE wzrost > mm;
END wysocy;
Dla procedury ze zdefiniowan
ą
warto
Ğ
ci
ą
domy
Ğ
ln
ą
poprawne jest wywo
á
anie, w któ-
rym podajemy warto
Ğü
posiadaj
ą
cego j
ą
parametru. Wówczas warto
Ğü
podana przy
wywo
á
aniu „nadpisuje” si
Ċ
na domy
Ğ
ln
ą
.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(1.8,ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Je
Ī
eli jednak chcemy przy tak zdefiniowanych parametrach odwo
á
a
ü
si
Ċ
do warto
Ğ
ci do-
my
Ğ
lnej, to musimy zastosowa
ü
wywo
á
anie nazewnicze o postaci
parametr=>zmienna
,
gdzie
parametr
jest nazw
ą
parametru formalnego procedury, a
zmienna
jest warto
Ğ
ci
ą
aktualn
ą
tego parametru w miejscu, z którego j
ą
wywo
á
ujemy. Notacj
Ċ
t
Ċ
mo
Ī
emy
odczytywa
ü
jako „
parametr staje siĊ zmienną
”. W przypadku takiego wywo
á
ania
zmienna, która nie zosta
á
a w nim wymieniona, b
Ċ
dzie mia
á
a przypisan
ą
warto
Ğü
domy
Ğ
ln
ą
.
Gdyby w definicji procedury pomini
Ċ
ta w wywo
á
aniu zmienna nie mia
á
a zdefiniowanej
warto
Ğ
ci domy
Ğ
lnej, to takie wywo
á
anie spowodowa
á
oby wy
Ğ
wietlenie komunikatu
o b
áĊ
dzie.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(ile => ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
W definicji procedury zmieniamy kolejno
Ğü
parametrów tak,
Ī
e drugi z nich ma przy-
pisan
ą
warto
Ğü
domy
Ğ
ln
ą
. Reszta procedury pozostaje bez zmian.
168
CzöĈè II i ORACLE PL/SQL
CREATE OR REPLACE PROCEDURE wysocy
(ile OUT NUMBER, mm NUMBER DEFAULT 1.7)
IS
BEGIN
SELECT COUNT(wzrost) INTO ile FROM Osoby
WHERE wzrost > mm;
END wysocy;
W takim przypadku, poniewa
Ī
przy odwo
á
aniu do warto
Ğ
ci domy
Ğ
lnej pomijamy ostatni
parametr, dopuszczalne jest zastosowanie wywo
á
ania pozycyjnego. Jest ono dozwolone
wtedy, gdy pomini
Ċ
ciu podlega
n
ostatnich parametrów posiadaj
ą
cych warto
Ğ
ci domy
Ğ
lne.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Oczywi
Ğ
cie bardziej ogólne jest wywo
á
anie nazewnicze, które, bez wzgl
Ċ
du na to, na
których pozycjach znajduj
ą
si
Ċ
warto
Ğ
ci domy
Ğ
lne, jest zawsze poprawne.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(ile => ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Wywo
á
anie nazewnicze jest dopuszczalne równie
Ī
wtedy, kiedy podajemy pe
á
ny ze-
staw parametrów. W takim przypadku kolejno
Ğü
ich wymieniania nie odgrywa
Ī
adnej roli.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(mm=>1.8, ile=>ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Do wersji 11. mo
Ī
liwe by
á
o stosowanie albo tylko wywo
á
ania pozycyjnego, albo na-
zewniczego — jednoczesne u
Ī
ycie obu tych typów nie by
á
o dozwolone. Od wersji 11.
istnieje ju
Ī
taka mo
Ī
liwo
Ğü
. Przeanalizujmy to na przyk
á
adzie procedury o trzech pa-
rametrach numerycznych. Pierwsze dwa s
ą
typu
IN
, a trzeci typu
OUT
. W ciele proce-
dury warto
Ğü
parametru wyj
Ğ
ciowego c jest wyznaczana w postaci ilorazu dwóch pierw-
szych parametrów.
CREATE OR REPLACE PROCEDURE dziel
(a real, b real, c OUT real)
AS
BEGIN
c:=a/b;
END;
Rozdziaä 7. i Procedury skäadowane
169
W przyk
á
adowym skrypcie pokazane zosta
á
y poprawne wywo
á
ania tej procedury:
w pe
á
ni pozycyjne, z dwoma pierwszymi parametrami danymi pozycyjnie oraz z danym
pozycyjnie pierwszym parametrem.
DECLARE
res real;
BEGIN
dziel(10, 9, res);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
dziel(10, 9, c => res);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
dziel(10, b => 9, c => res);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
dziel(10, c => res, b => 9);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
END;
Nie ka
Ī
de wywo
á
anie mieszane jest jednak dopuszczalne. Dozwolone s
ą
tylko takie
przypadki, w których pierwsze na li
Ğ
cie parametry podstawiane s
ą
pozycyjnie, a po-
zosta
á
e nazewniczo. Kolejny przyk
á
ad pokazuje niepoprawne u
Ī
ycie wywo
á
ania mie-
szanego, gdzie b
áą
d polega na tym,
Ī
e
Ğ
rodkowy parametr jest dany nazewniczo, czyli,
inaczej mówi
ą
c,
Ī
e po parametrze danym nazewniczo istnieje cho
ü
jeden dany pozy-
cyjnie.
DECLARE
res real;
BEGIN
dziel(10, b => 9, res);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
END;
W przypadku próby wykonania takiego bloku anonimowego wygenerowany zostanie
komunikat o b
áĊ
dzie w nast
Ċ
puj
ą
cej postaci:
Error report:
ORA-06550: linia 12, kolumna 15:
PLS-00312: skojarzenie parametrów przez nazwú moľe nie implikowaè skojarzenia przez pozycjú
ORA-06550: linia 12, kolumna 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Ciekaw
ą
mo
Ī
liwo
Ğ
ci
ą
zastosowania procedury jest wykonywanie zapyta
Ĕ
sk
á
adanych
z fragmentów, np. danych statycznymi napisami czy te
Ī
zawartych w zmiennej. Zbu-
dujmy procedur
Ċ
, która w zale
Ī
no
Ğ
ci od warto
Ğ
ci parametru zmieni sposób zapisu pola
Nazwisko
w tabeli
Osoby
. Wykonanie takiego zapytania, sk
á
adaj
ą
cego si
Ċ
z fragmentów
napisów, wymaga u
Ī
ycia polecenia
EXECUTE IMMEDIATE
.
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
BEGIN
EXECUTE IMMEDIATE
'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
END exe_tekst;
170
CzöĈè II i ORACLE PL/SQL
Bardziej eleganckim rozwi
ą
zaniem jest zastosowanie zmiennej pomocniczej
zap
, co
oczywi
Ğ
cie nie wp
á
ywa na sposób wykonania. Przyk
á
ad ten pokazuje natomiast,
Ī
e miej-
scem deklaracji zmiennych lokalnych procedury (takich, które s
ą
widoczne tylko w jej
ciele) jest obszar mi
Ċ
dzy s
á
owami kluczowymi
IS
oraz
BEGIN
. Przy deklarowaniu zmien-
nych w tym miejscu nie wolno stosowa
ü
s
á
owa kluczowego
DECLARE
.
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
zap varchar2(111);
BEGIN
zap:= 'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
EXECUTE IMMEDIATE zap
END exe_tekst;
Przy okazji prezentowania tego przyk
á
adu chc
Ċ
przedstawi
ü
nieco archaiczne wywo-
á
anie procedury z zastosowaniem polecenia
CALL
. Poprawnymi parametrami s
ą
tu na-
zwy funkcji operuj
ą
cych na zmiennych
á
a
Ĕ
cuchowych:
UPPER
— przepisanie
á
a
Ĕ
cucha
do postaci pisanej tylko du
Ī
ymi literami,
LOWER
— przepisanie
á
a
Ĕ
cucha do postaci pi-
sanej tylko ma
á
ymi literami,
INITCAP
— przepisanie
á
a
Ĕ
cucha do postaci pisanej od
du
Ī
ej litery. Poprawne jest równie
Ī
u
Ī
ycie pustego ci
ą
gu znaków
''
lub ci
ą
gu sk
á
a-
daj
ą
cego si
Ċ
z samych spacji
' '
. Zalet
ą
tego typu wywo
á
ania jest mo
Ī
liwo
Ğü
za-
stosowania bezpo
Ğ
rednio po nim zapytania wybieraj
ą
cego, które ma za zadanie spraw-
dzi
ü
poprawno
Ğü
wykonania procedury.
CALL exe_tekst('UPPER');
SELECT * FROM osoby;
W wi
Ċ
kszo
Ğ
ci sytuacji b
Ċ
dziemy jednak stosowa
ü
klasyczne wywo
á
anie wewn
ą
trz bloku
anonimowego. W takim przypadku zastosowanie w nim zapytania wybieraj
ą
cego zgod-
nie z wymogami sk
á
adni nie jest dozwolone, je
Ğ
li jednak chcemy w ramach tego sa-
mego skryptu wykona
ü
blok anonimowy i zapytanie wybieraj
ą
ce, musimy rozdzieli
ü
je
znakiem
/
. Faktycznie powoduje to,
Ī
e pomimo tego, i
Ī
oba elementy zapisane s
ą
w tym
samym miejscu, stanowi
ą
one dwa przetwarzane po sobie skrypty — jeden PL/SQL,
drugi SQL. Ka
Ī
dy d
á
u
Ī
szy skrypt mo
Ī
e zosta
ü
podzielony znakami
/
na mniejsze frag-
menty, które b
Ċ
d
ą
przetwarzane szeregowo, oczywi
Ğ
cie pod warunkiem,
Ī
e ka
Ī
dy z nich
jest sk
á
adniowo poprawny.
BEGIN
exe_tekst('INITCAP');
END;
/
SELECT * FROM osoby;
Kolejny przyk
á
ad przedstawia zastosowanie w definicji procedury wywo
á
ania wbudo-
wanej procedury
RAISE_APPLICATION_ERROR
, która powoduje wygenerowanie (ustano-
wienie) b
áĊ
du u
Ī
ytkownika o numerze danym pierwszym parametrem oraz komuni-
kacie stanowi
ą
cym drugi z parametrów. Nale
Ī
y zauwa
Ī
y
ü
,
Ī
e numeracja b
áĊ
dów w Oracle
przebiega przez warto
Ğ
ci ujemne, a dla b
áĊ
dów u
Ī
ytkownika zarezerwowano przedzia
á
<–29999, –20001>.
Wywo
á
anie powy
Ī
szej procedury powoduje przerwanie dzia
á
ania
programu i wy
Ğ
wietlenie komunikatu o b
áĊ
dzie.
Rozdziaä 7. i Procedury skäadowane
171
CREATE OR REPLACE PROCEDURE Blad
IS
BEGIN
RAISE_APPLICATION_ERROR (-20205, 'Bđæd programu');
END blad;
Bardziej z
á
o
Ī
onym przyk
á
adem zastosowania
RAISE_APPLICATION_ERROR
jest wykorzy-
stanie jej podczas wykonywania procedury o ograniczonym zestawie danych wej-
Ğ
ciowych, co ma miejsce np. w opracowanej poprzednio procedurze
exe_tekst
. Je
Ī
eli
parametr wej
Ğ
ciowy nie jest jednym z dopuszczalnych elementów wymienionych na
li
Ğ
cie, generowany jest b
áą
d z odpowiednim komentarzem. W przeciwnym przypadku
wykonywane jest za pomoc
ą
polecenia
EXECUTE IMMEDIATE
zapytanie. Nale
Ī
y zwróci
ü
uwag
Ċ
na fakt,
Ī
e do porównania z elementami listy u
Ī
yto zmiennej przetworzonej do
postaci pisanej du
Ī
ymi literami
UPPER(typ)
, gdy
Ī
przy porównywaniu
á
a
Ĕ
cuchów
Oracle rozró
Ī
nia ich wielko
Ğü
. Pozwala to na podanie w wywo
á
aniu procedury nazwy
funkcji modyfikuj
ą
cej
á
a
Ĕ
cuch pisanej w dowolny sposób (literami ma
á
ymi, du
Ī
ymi oraz
ró
Ī
nej wielko
Ğ
ci).
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
BEGIN
IF UPPER(typ) NOT IN('UPPER', 'LOWER', 'INITCAP') THEN
RAISE_APPLICATION_ERROR (-20205, 'Zđa funkcja');
ELSE
EXECUTE IMMEDIATE
'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
END IF;
END exe_tekst;
Mo
Ī
emy przekszta
á
ci
ü
procedur
Ċ
, tak aby w jej ciele u
Ī
y
ü
wywo
á
ania poprzednio utwo-
rzonej procedury generuj
ą
cej b
áą
d przetwarzania o nazwie
Blad
.
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
zap varchar2(111);
BEGIN
IF UPPER(typ) NOT IN('UPPER', 'LOWER', 'INITCAP') THEN
Blad;
ELSE
zap:= 'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
EXECUTE IMMEDIATE zap;
END IF;
END exe_tekst;
B
áĊ
dy mog
ą
si
Ċ
jednak pojawia
ü
podczas przetwarzania nie tylko na skutek celowej
dzia
á
alno
Ğ
ci programisty, ale mog
ą
by
ü
te
Ī
spowodowane nie zawsze daj
ą
cymi si
Ċ
przewidzie
ü
zdarzeniami, b
áĊ
dnymi wywo
á
aniami, nieodpowiednimi parametrami etc.
Mo
Ī
emy mówi
ü
wtedy o sytuacji wyj
ą
tkowej — o powstaniu wyj
ą
tku. Takie zdarzenia
mog
ą
zosta
ü
w PL/SQL obs
á
u
Ī
one, oprogramowane.
172
CzöĈè II i ORACLE PL/SQL
Rozwa
Ī
my przyk
á
ad procedury, której zadaniem jest okre
Ğ
lenie, czy pracownik o danym
numerze identyfikacyjnym
IdOsoby
, wskazanym parametrem
num
, istnieje w tabeli
Osoby
. Je
Ğ
li tak, drugi z parametrów (
status
) ma przyj
ąü
warto
Ğü
1
; w przypadku
przeciwnym
0
. W celu realizacji tego zadania zastosowano zapytanie wybieraj
ą
ce zwra-
caj
ą
ce do zmiennej pomocniczej
kto
identyfikator osoby. Je
Ī
eli pracownik o danym
identyfikatorze istnieje, warto
Ğü
zwrócona przez zapytanie i warto
Ğü
parametru b
Ċ
d
ą
takie same, je
Ğ
li jednak takiego pracownika nie ma, zapytanie wybieraj
ą
ce nie zwróci
Ī
adnego wiersza. Spowoduje to,
Ī
e próba podstawienia pod zmienn
ą
kto
zako
Ĕ
czy si
Ċ
b
áĊ
dem przetwarzania:
Nie znaleziono Īadnych wierszy
. Stan ten mo
Ī
emy wykorzy-
sta
ü
, wprowadzaj
ą
c sekcj
Ċ
EXCEPTION
i oprogramowuj
ą
c wyj
ą
tek
NO_DATA_FOUND
, któ-
rego obs
á
uga wykonywana jest wed
á
ug schematu
WHEN nazwa_wyjætku THEN instrukcje
.
W naszym przypadku obs
á
uga wyj
ą
tku zawiera podstawienie odpowiedniej warto
Ğ
ci pod
zmienn
ą
status
oraz wypisanie komunikatu.
CREATE OR REPLACE PROCEDURE czy_jest
(num IN NUMBER, status OUT NUMBER)
IS
kto NUMBER;
BEGIN
SELECT IdOsoby INTO kto
ROM Osoby WHERE IdOsoby = num;
IF (kto = num) THEN
status := 1;
DBMS_OUTPUT.PUT_LINE ('Pracownik istnieje');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
status := 0;
DBMS_OUTPUT.PUT_LINE('Pracownik nie istnieje');
WHEN OTHERS THEN
NULL;
END;
W
Ğ
rodowisku Oracle zdefiniowano wiele wyj
ą
tków, których nazwy symboliczne i przy-
czyny wyst
ą
pienia zawiera tabela 7.1. Je
Ī
eli gdziekolwiek w ciele procedury wyst
Ċ
puje
sytuacja wyj
ą
tkowa, przetwarzanie przenoszone jest do sekcji obs
á
ugi wyj
ą
tków. Naj-
pierw sprawdzane jest to, czy wyj
ą
tek, który przerwa
á
przetwarzanie, jest zgodny z nazw
ą
symboliczn
ą
wyst
Ċ
puj
ą
c
ą
w sekcji
EXCEPTION
. Nast
Ċ
pnie wykonywane s
ą
instrukcje znaj-
duj
ą
ce si
Ċ
po s
á
owie kluczowym
THEN
jego obs
á
ugi, po czym przerywane jest przetwa-
rzanie procedury i nast
Ċ
puje powrót do miejsca, z którego zosta
á
a ona wywo
á
ana. Je
Ğ
li
w trakcie przetwarzania procedury pojawi
ą
si
Ċ
jednocze
Ğ
nie dok
á
adnie dwa wyj
ą
tki,
co jest mo
Ī
liwe, chocia
Ī
ma
á
o prawdopodobne, to obs
á
u
Ī
ony zostanie tylko ten, który
wyst
Ċ
puje jako pierwszy na li
Ğ
cie w sekcji obs
á
ugi wyj
ą
tków. Na szczególn
ą
uwag
Ċ
zas
á
uguje wyj
ą
tek o nazwie
OTHERS
, który obs
á
uguje wszystkie inne, dot
ą
d nieobs
á
u-
Ī
one. Gdyby znalaz
á
si
Ċ
on na pierwszym miejscu listy obs
á
ugi wyj
ą
tków, to bez wzgl
Ċ
du
na to, jakie zdarzenie powodowa
á
oby wyst
ą
pienie sytuacji wyj
ą
tkowej, wykonywana
by
á
aby zawsze ta sama sekcja znajduj
ą
ca si
Ċ
po
OTHERS
. Od wersji 9. Oracle umiesz-
czanie obs
á
ugi wyj
ą
tku
OTHERS
przed obs
á
ug
ą
jakiegokolwiek innego jest zabronione
sk
á
adniowo. Innymi s
á
owy, jego obs
á
uga musi by
ü
ostatnim elementem sekcji obs
á
ugi
wyj
ą
tków. W prezentowanym przyk
á
adzie zastosowano minimaln
ą
obs
á
ug
Ċ
wyj
ą
tku
(sekcja nie mo
Ī
e by
ü
pusta) —
NULL
, nie rób nic. Bez wzgl
Ċ
du na to, czy wyj
ą
tki s
ą
w pro-
cedurze obs
á
ugiwane, czy te
Ī
nie, zasady jej wywo
á
ania pozostaj
ą
bez zmian.
Rozdziaä 7. i Procedury skäadowane
173
Tabela 7.1. Wykaz najczĊĞciej wystĊpujących wyjątków serwera
Nazwa wyjñtku
Numer bäödu
Opis
NO_DATA_FOUND
ORA-01403
Jednowierszowe zapytanie wybieraj
ą
ce
SELECT
nie zwróci
á
o
danych.
TOO_MANY_ROWS
ORA-01422
Zapytanie wybieraj
ą
ce
SELECT
zwróci
á
o wi
Ċ
cej ni
Ī
jeden wiersz.
INVALID_CURSOR
ORA-01001
Niedopuszczalna operacja na kursorze.
ZERO_DIVIDE
ORA-01476
Próba dzielenia przez zero.
DUP_VAL_ON_INDEX
ORA-00001
Próba wstawienia powtarzaj
ą
cej si
Ċ
warto
Ğ
ci w pole,
dla którego ustanowiono indeks unikatowy.
INVALID_NUMBER
ORA-01722
Konwersja
á
a
Ĕ
cucha na liczb
Ċ
zako
Ĕ
czy
á
a si
Ċ
niepowodzeniem.
CURSOR_ALREADY_OPEN
ORA-06511
Próba otwarcia kursora, który ju
Ī
zosta
á
otwarty.
LOGIN_DENIED
ORA-01017
Próba zalogowania si
Ċ
z nieodpowiednim has
á
em lub loginem.
NOT_LOGGED_ON
ORA-01012
Próba wykonania polecenia operuj
ą
cego na bazie danych
bez uprzedniego zalogowania si
Ċ
.
PROGRAM_ERROR
ORA-06501
PL/SQL napotka
á
wewn
Ċ
trzny problem podczas przetwarzania.
STORAGE_ERROR
ORA-06500
PL/SQL dysponuje zbyt ma
á
ymi zasobami pami
Ċ
ci
lub pami
Ċü
zosta
á
a uszkodzona.
TIMEOUT_ON_RESOURCE
ORA-00051
Zosta
á
przekroczony czas oczekiwania na odpowied
Ĩ
bazy danych.
ACCESS_INTO_NULL
ORA-06530
Próba przypisania do zmiennej warto
Ğ
ci niezainicjowanej
(
NULL
).
CASE_NOT_FOUND
ORA-06592
ĩ
adna z warto
Ğ
ci okre
Ğ
lonych warunkami
WHEN
w poleceniu
CASE
nie jest prawdziwa, a nie wyst
Ċ
puje sekcja
ELSE
.
Wywo
á
anie pozycyjne procedury mo
Ī
e mie
ü
posta
ü
:
SET SERVEROUTPUT ON;
DECLARE
kto NUMBER;
status NUMBER;
BEGIN
kto:=1;
czy_jest (kto, status);
DBMS_OUTPUT.PUT_LINE(status);
END;
Wywo
á
anie nazewnicze mo
Ī
na zrealizowa
ü
wed
á
ug schematu:
SET SERVEROUTPUT ON;
DECLARE
kto NUMBER;
status NUMBER;
BEGIN
kto := 1;
czy_jest (status => status, num => kto);
DBMS_OUTPUT.PUT_LINE(status);
END;
174
CzöĈè II i ORACLE PL/SQL
Przedstawiony poprzednio przyk
á
ad jest niew
ą
tpliwie akademicki, poniewa
Ī
wyko-
rzystuje sekcj
Ċ
obs
á
ugi wyj
ą
tków do wyznaczania parametru
OUT
. W praktyce, je
Ğ
li
w tym miejscu jest wyznaczany jaki
Ğ
parametr wyj
Ğ
ciowy, to jest on odpowiedzialny
za kodowanie sposobu zako
Ĕ
czenia przetwarzania, np.
0
— przetwarzanie zako
Ĕ
czone
sukcesem,
<>0
— przetwarzanie zako
Ĕ
czone niepowodzeniem; konkretna warto
Ğü
ko-
duje przyczyn
Ċ
. Nasz
ą
procedur
Ċ
mogliby
Ğ
my wi
Ċ
c doprowadzi
ü
do postaci, w której
wykorzystywaliby
Ğ
my funkcj
Ċ
agreguj
ą
c
ą
COUNT
.
CREATE OR REPLACE PROCEDURE czy_jest
(num IN NUMBER, status OUT NUMBER, ok OUT NUMBER)
IS
BEGIN
ok:=0;
SELECT COUNT(IdOsoby) INTO status
FROM Osoby WHERE IdOsoby = num;
IF (status = 1) THEN
DBMS_OUTPUT.PUT_LINE ('Pracownik istnieje');
ELSE
DBMS_OUTPUT.PUT_LINE('Pracownik nie istnieje');
END IF;
EXCEPTION
WHEN OTHERS THEN
ok := 99;
DBMS_OUTPUT.PUT_LINE('Bđæd przetwarzania');
END;
Zamiana zapytania wybieraj
ą
cego na takie, które zawiera funkcj
Ċ
zliczaj
ą
c
ą
rekordy,
spowoduje,
Ī
e je
Ğ
li pracownik o danym numerze istnieje, to policzony zostanie
1
re-
kord, a je
Ğ
li nie istnieje —
0
rekordów. Jak wida
ü
, zmiana taka sprawia,
Ī
e przypisanie
mo
Ī
e od razu dotyczy
ü
zmiennej wychodz
ą
cej oraz
Ī
e wyj
ą
tek
NO_DATA_FOUND
nie po-
jawia si
Ċ
. Zawsze jednak mo
Ī
liwe jest wyst
ą
pienie innych b
áĊ
dów przetwarzania, st
ą
d
obs
á
uga wyj
ą
tku
OTHERS
, w której ustawiono zmienn
ą
ok
na warto
Ğü
ró
Ī
n
ą
od zera, w tym
przypadku
99
, co koduje stan pojawienia si
Ċ
b
áĊ
du. Zwyczajowo pierwsz
ą
linijk
ą
cia
á
a
procedury jest ustawienie zmiennej koduj
ą
cej sposób wykonania na
0
— przetwarza-
nie zako
Ĕ
czone poprawnie.
Istnieje formalna mo
Ī
liwo
Ğü
obs
á
u
Ī
enia dwóch lub wi
Ċ
cej wyj
ą
tków w tym samym
miejscu sekcji ich obs
á
ugi. W tym celu po s
á
owie kluczowym
WHEN
áą
czymy nazwy sym-
boliczne wyj
ą
tków operatorem logicznym
OR
.
CREATE OR REPLACE PROCEDURE czy_jest
(num IN NUMBER, status OUT NUMBER, ok OUT NUMBER)
IS
BEGIN
ok := 0;
SELECT COUNT(IdOsoby) INTO status
FROM Osoby WHERE IdOsoby = num;
IF (status = 1) THEN
DBMS_OUTPUT.PUT_LINE ('Pracownik istnieje');
ELSE
DBMS_OUTPUT.PUT_LINE('Pracownik nie istnieje');
END IF;
EXCEPTION
WHEN INVALID_NUMBER OR NO_DATA_FOUND THEN
Rozdziaä 7. i Procedury skäadowane
175
ok := 11;
DBMS_OUTPUT.PUT_LINE('Bđæd wartoħci');
WHEN OTHERS THEN
ok := 99;
DBMS_OUTPUT.PUT_LINE('Bđæd przetwarzania');
END;
Nie zawsze jest tak,
Ī
e wyj
ą
tek musi wi
ą
za
ü
si
Ċ
z formalnym b
áĊ
dem przetwarzania.
Czasami wygodnym jest, aby pewne sytuacje nieprowadz
ą
ce do b
áĊ
dów formalnych
by
á
y traktowane jako wyj
ą
tkowe. Mówimy wtedy o wyj
ą
tkach u
Ī
ytkownika, które musz
ą
zosta
ü
zdefiniowane, wykryte i które powinny zosta
ü
obs
á
u
Ī
one. W prezentowanym
przyk
á
adzie za sytuacj
Ċ
wyj
ą
tkow
ą
b
Ċ
dziemy chcieli uzna
ü
fakt,
Ī
e nie ma osób o wzro-
Ğ
cie wy
Ī
szym od progu danego parametrem. Jak wida
ü
, taka sytuacja nie spowoduje
powstania b
áĊ
du przetwarzania — trzeba wi
Ċ
c j
ą
wykry
ü
.
CREATE OR REPLACE PROCEDURE licz
(mini NUMBER, ile out INT)
IS
brakuje EXCEPTION;
BEGIN
SELECT COUNT(IdOsoby) INTO ile FROM Osoby
WHERE Wzrost > mini;
IF (ile = 0) THEN
RAISE brakuje;
END IF;
EXCEPTION
WHEN brakuje THEN
RAISE;
WHEN OTHERS THEN
NULL;
END;
Deklaracji wyj
ą
tku u
Ī
ytkownika, tak samo jak ka
Ī
dej innej zmiennej, dokonujemy
w sekcji deklaracji i nadajemy mu typ
EXCEPTION
(jak wida
ü
, to s
á
owo kluczowe pe
á
ni
podwójn
ą
rol
Ċ
: jest okre
Ğ
leniem typu oraz sygnalizuje pocz
ą
tek sekcji obs
á
ugi wyj
ą
tków).
W przyk
á
adzie zdefiniowano wyj
ą
tek o nazwie brakuje. Po zliczeniu osób o wzro
Ğ
cie
wy
Ī
szym od warto
Ğ
ci progowej instrukcj
ą
warunkow
ą
sprawdzono, czy ich liczba jest
równa
0
, po czym dla takiego przypadku poleceniem
RAISE nazwa_wyjætku
ustawiono
(wygenerowano) b
áą
d u
Ī
ytkownika. Obs
á
ugi wyj
ą
tku u
Ī
ytkownika dokonujemy na ta-
kich samych zasadach jak wyj
ą
tków wbudowanych (systemowych). W przyk
á
adzie za-
stosowano drug
ą
, po minimalnej obs
á
udze
NULL
, najcz
ĊĞ
ciej spotykan
ą
metod
Ċ
— u
Ī
ycie
polecenia
RAISE
, które odpowiada za wygenerowanie wyj
ą
tku. Spowoduje to propa-
gacj
Ċ
wyj
ą
tku do miejsca, z którego procedura zosta
á
a wywo
á
ana. Mo
Ī
na powiedzie
ü
,
Ī
e nie da si
Ċ
z sekcji obs
á
ugi wyj
ą
tków przenie
Ğü
si
Ċ
do tej samej sekcji, wi
Ċ
c wyj
ą
tek
zg
á
oszony w sekcji obs
á
ugi wyj
ą
tków musi zosta
ü
obs
á
u
Ī
ony „pi
Ċ
tro wy
Ī
ej” — w pro-
cedurze wywo
á
uj
ą
cej.
Bardzo cz
Ċ
sto wykorzystujemy przy obs
á
udze wyj
ą
tków dwie wbudowane funkcje
PL/SQL:
SQLCODE
— zwracaj
ą
c
ą
numer wyj
ą
tku (b
áĊ
du), oraz
SQLERRM
— wy
Ğ
wietla-
j
ą
c
ą
zwi
ą
zany z tym b
áĊ
dem (wyj
ą
tkiem) komunikat. Sposób ich zastosowania ilustruje
nast
Ċ
pny przyk
á
ad.