��IDZ DO
IDZ DO
PRZYK�ADOWY ROZDZIA�
PRZYK�ADOWY ROZDZIA�
Oracle PL/SQL.
SPIS TRE CI
SPIS TRE CI
Wprowadzenie
KATALOG KSI��EK
KATALOG KSI��EK
Oracle PL/SQL. Wprowadzenie
KATALOG ONLINE
KATALOG ONLINE Autorzy: Bill Pribyl, Steven Feuerstein
T�umaczenie: Bart�omiej Garbacz
ISBN: 83-7197-727-1
ZAM�W DRUKOWANY KATALOG
ZAM�W DRUKOWANY KATALOG
Tytu� orygina�u: Learning Oracle PL/SQL
Format: B5, stron: 412
TW�J KOSZYK Przyk�ady na ftp: 118 kB
TW�J KOSZYK
PL-SQL j�zyk programowania systemu Oracle, przeznaczony do tworzenia procedur
DODAJ DO KOSZYKA
DODAJ DO KOSZYKA
magazynowanych zapewnia ogromne mo�liwo ci pisz�cym oprogramowanie baz
danych. PL/SQL rozszerza standard j�zyka relacyjnych baz danych SQL poprzez
umo�liwienie korzystania z takich konstrukcji, jak: p�tle, instrukcje IF-THEN, z�o�one
CENNIK I INFORMACJE
CENNIK I INFORMACJE
struktury danych czy szerokie mo�liwo ci kontroli operacji transakcyjnych. Wszystkie
z nich s� ci le zintegrowane z serwerem bazy danych Oracle.
ZAM�W INFORMACJE
ZAM�W INFORMACJE
O NOWO CIACH
O NOWO CIACH
Oracle PL/SQL. Wprowadzenie daje Czytelnikowi mo�liwo � pe�nego zrozumienia
j�zyka PL/SQL bez wzgl�du na to, czy jest pocz�tkuj�cym, czy do wiadczonym
ZAM�W CENNIK programist�. W niniejszej ksi��ce przedstawiono nast�puj�ce zagadnienia:
ZAM�W CENNIK
" cechy j�zyka PL/SQL i korzy ci wynikaj�cych z jego u�ywania;
" sk�adnia i przyk�ady zastosowania wszystkich g��wnych konstrukcji j�zyka;
CZYTELNIA
CZYTELNIA
" tworzenie i wykorzystywanie procedur, funkcji oraz pakiet�w magazynowanych;
" tworzenie aplikacji opartych na sieci Internet;
FRAGMENTY KSI��EK ONLINE
FRAGMENTY KSI��EK ONLINE
" zabezpieczanie program�w w j�zyku PL/SQL przed atakami z zewn�trz;
" korzy ci wynikaj�ce z wykorzystania narz�dzi wspomagaj�cych programowanie,
pochodz�cych od innych dostawc�w;
" wykorzystanie j�zyka PL/SQL do programowania zada� zwi�zanych z u�yciem
poczty elektronicznej, j�zyka Java oraz sieci Internet.
Oracle PL/SQL. Wprowadzenie zawiera szczeg��owy opis konstrukcji j�zyka we
wszystkich wersjach od Oracle7 do Oracle9i, podparty przyk�adami program�w
dost�pnych tak�e pod adresem http://oracle.oreilly.com. Autorami jej s� eksperci
j�zyka PL/SQL Bill Pribyl oraz Steven Feuerstein. Ksi��ka daje solidne podstawy
ka�demu programi cie baz danych i administratorowi, kt�ry zmuszony jest do poznania
j�zyka PL/SQL.
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
RozdziaB 1.
Podstawy j�zyka PL/SQL ........................................................................................................ 19
Zalety j�zyka PL/SQL ............................................................................................................. 27
Wymagania dotyczce stosowania j�zyka PL/SQL ................................................................ 33
RozdziaB 2.
Podstawy skBadni ..................................................................................................................... 38
Pierwszy program w PL/SQL.................................................................................................. 40
Wprowadzenie do budowy programu...................................................................................... 44
Zmienne ................................................................................................................................... 48
Podstawowe operatory............................................................................................................. 56
Wyra|enia warunkowe ............................................................................................................ 63
Instrukcje wykonywania w p�tlach ......................................................................................... 67
Formatowanie kodu: wymagania i wskaz�wki ....................................................................... 73
Podstawy bardziej zBo|onych zagadnieD ................................................................................. 75
RozdziaB 3.
Informacje o programie przykBadowym .................................................................................. 81
Pierwsze zadanie programistyczne.......................................................................................... 83
Pobieranie informacji o liczbie ksi|ek za pomoc funkcji .................................................... 97
Tworzenie elastycznego kodu................................................................................................ 102
Wykorzystanie pakiet�w PL/SQL w celu organizacji kodu.................................................. 108
Przej[cie na wy|szy poziom .................................................................................................. 117
Dalsza droga .......................................................................................................................... 122
RozdziaB 4.
Wprowadzenie do HTML...................................................................................................... 124
Tworzenie stron internetowych za pomoc j�zyka PL/SQL ................................................. 134
Inne zagadnienia .................................................................................................................... 167
RozdziaB 5.
Wprowadzenie ....................................................................................................................... 170
Prosta metoda: pobierania danych z jednego wiersza ........................................................... 170
Pobieranie wielu wierszy za pomoc kursora........................................................................ 172
Prezentowanie wynik�w zapytania na stronie WWW .......................................................... 184
Tworzenie strony WWW sBu|cej do wyszukiwania
za pomoc mechanizmu dynamicznego SQL ..................................................................... 188
Zaawansowane zagadnienia zwizane z pobieraniem danych .............................................. 205
RozdziaB 6.
Organizowanie kodu.............................................................................................................. 215
Narz�dzia pomagajce w efektywnym programowaniu........................................................ 228
RozdziaB 7.
Podstawy bezpieczeDstwa w systemie Oracle....................................................................... 246
Organizowanie kont w celu zwi�kszenia poziomu zabezpieczeD ......................................... 255
Analiza wymagaD systemu bibliotecznego............................................................................ 267
Zledzenie zmian w bazie danych ........................................................................................... 273
Szczeg�lne kwestie bezpieczeDstwa zwizane z programowaniem w PL/SQL ................... 281
RozdziaB 8.
WysyBanie wiadomo[ci poczt elektroniczn za pomoc PL/SQL ....................................... 288
Wykorzystanie narz�dzia sBu|cego do wysyBania wiadomo[ci elektronicznych
w systemie bibliotecznym ................................................................................................... 293
Odbieranie wiadomo[ci z poziomu bazy danych .................................................................. 296
Pobieranie danych ze zdalnych stron internetowych............................................................. 305
Integracja z innymi j�zykami programowania ...................................................................... 317
RozdziaB 9.
Cykle istnienia oprogramowania ........................................................................................... 324
Listy obiekt�w (kolekcje) w j�zyku PL/SQL ........................................................................ 326
Pakiety obsBugi wyjtk�w...................................................................................................... 339
Kontrola transakcji................................................................................................................. 343
Kompilator PL/SQL............................................................................................................... 349
Zarzdzanie uprawnieniami czytelnik�w i bibliotekarzy...................................................... 352
Inne cechy PL/SQL................................................................................................................ 372
Programowanie a bazy danych .............................................................................................. 381
Fakty ...................................................................................................................................... 381
W niniejszym rozdziale om�wiono nastpujce zagadnienia:
" Informacje o programie przykBadowym
" Pierwsze zadanie programistyczne
" Pobieranie informacji o liczbie ksi|ek za pomoc funkcji
" Tworzenie elastycznego kodu
" Wykorzystanie pakiet�w PL/SQL w celu organizacji kodu
" Przej[cie na wy|szy poziom
" Dalsza droga
Po zapoznaniu si� z podstawami j�zyka PL/SQL Czytelnik jest przygotowany do tworzenia pro-
gram�w bardziej rozbudowanych ni| zwykBe wy[wietlanie komunikatu. W niniejszym rozdziale
przedstawiono spos�b rozpocz�cia tworzenia aplikacji obsBugi katalogu biblioteki. W kolejnych cz�-
[ciach ksi|ki opisano spos�b jej dalszej rozbudowy. Nowymi elementami j�zyka PL/SQL, kt�re
przedstawiono w niniejszym rozdziale, s procedury (procedures), funkcje (functions) oraz pakiety
(packages). Czytelnik dowie si�, do czego te elementy sBu|, jak je konstruowa oraz w jaki spo-
s�b u|ywa w celu osigni�cia wymaganych cel�w.
PrzykBadowe zadanie programistyczne, opisane w niniejszej ksi|ce, polega na pr�bie utworzenia
systemu, kt�ry sBu|yBby do katalogowania oraz wyszukiwania ksi|ek w bibliotece jest to rodzaj
elektronicznego katalogu. W przypadku tej hipotetycznej biblioteki zakBada si�, |e wszelkie dane
operacyjne znajduj si� w bazie danych Oracle. Istnieje wi�cej ni| jeden spos�b gromadzenia danych
dotyczcych tytuB�w, autor�w itp. w bazie danych. Jednym z nich jest r�czne wpisywanie
danych przez bibliotekarza. W kolejnych rozdziaBach zostan opisane metody automatycznego Ba-
dowania danych z odlegBych zr�deB oraz metody wyszukiwania przez u|ytkownika danych znajduj-
cych si� w katalogu.
Istnieje konieczno[ speBnienia dw�ch wymagaD o podstawowym znaczeniu dla dziaBania opisywa-
nej aplikacji:
" Nale|y umo|liwi tworzenie wpis�w do katalogu dla ka|dej nowej ksi|ki.
" Nale|y udost�pni mo|liwo[ okre[lania liczby egzemplarzy danej ksi|ki, znajdujcych si�
w zasobach biblioteki.
W celu speBnienia pierwszego wymagania nale|y utworzy procedur� PL/SQL, sBu|c do wprowa-
dzania danych do bazy danych. Program umo|liwiajcy speBnienie drugiego warunku wymaga za-
stosowania funkcji PL/SQL. Przed opisaniem sposobu tworzenia tych element�w nale|y najpierw
przedstawi metody projektowania struktury samej bazy danych.
Podobnie jak w przypadku wi�kszo[ci projekt�w tworzonych przez programist�w PL/SQL, struktura
bazy danych dotyczcych ksi|ek w bibliotece zostaBa wcze[niej zaprojektowana i utworzona na
podstawie wymagaD postawionych przez przyszBego u|ytkownika. Podzbi�r logicznego projektu
bazy danych, zwizany ze wspomnianymi wcze[niej wymaganiami, mo|na ograniczy do infor-
macji o ka|dym egzemplarzu ksi|ki w bibliotece. Rysunek 3.1 przedstawia tak zwany diagram
zwizk�w encji (entity-relationship diagram, ERD).
Rysunek 3.1. Zale|no[ midzy wpisem (informacj) dotyczcym ksi|ki a jej fizycznie istniejcymi egzemplarzami
Diagramy takie w zwi�zBej i uproszczonej formie prezentuj informacje o realnym [wiecie. Opisane
w odpowiedni spos�b prostokty s encjami (entities) bazy danych, a linie pomi�dzy nimi ozna-
czaj zwizki (relationships) pomi�dzy encjami. Relacyjne bazy danych przedstawiaj rzeczywi-
sto[ w formie zbioru struktur danych (kt�re przechowuj informacje o pewnych obiektach) oraz zbio-
ru metod (kt�re definiuj powizania mi�dzy obiektami). Encja book reprezentuje podstawowe
informacje o ksi|ce (tytuB, autor itd.), kt�re zawiera ka|da biblioteka. Encja book_copy zawiera
informacje o fizycznie istniejcych egzemplarzach danej ksi|ki.
Pewne zdziwienie mo|e wywoBa fakt, |e caBo[ rozdzielono na dwie encje zamiast u|ycia jednej. Wy-
korzystanie tylko jednej encji spowodowaBaby jednak problemy w p�zniejszym czasie, poniewa| wy-
stpiBaby konieczno[ kopiowania informacji dotyczcych ksi|ki razem z informacjami dotyczcymi
jej pojedynczych egzemplarzy, co z pewno[ci byBoby niewBa[ciwym sposobem wykorzystania zaso-
b�w komputera i wysiBku ludzkiego. PeBna dyskusja na temat normalizacji (normalization) baz danych
(procesu organizowania danych w postaci tabel zgodnie z ich wewn�trzn struktur) wykracza poza
zakres tre[ci niniejszej ksi|ki. Warto jednak podkre[li, |e gB�wna idea polega na przechowywaniu
wa|nych informacji w jednym i tylko w jednym miejscu. Ka|dy kolejny egzemplarz danej ksi|ki wy-
maga utworzenia jedynie dodatkowego rekordu zawierajcego identyfikator, kt�ry w powy|szym przy-
padku jest numerem identyfikacyjnym pochodzcym z samoprzylepnej naklejki z kodem kreskowym.
W tym miejscu nale|y wyja[ni znaczenie linii przedstawiajcych relacj�, pokazan na rysunku 3.1.
Z tre[ci tego rysunku wynikaj nast�pujce fakty dotyczce realnej sytuacji:
" Ka|dy egzemplarz danej ksi|ki jest egzemplarzem tyko jednej ksi|ki.
" Ka|da ksi|ka mo|e posiada jeden lub wi�ksz liczb� swoich egzemplarzy.
Relacja taka jest znana jako relacja jeden-do-wielu (one-to-many relationship): jedna pozycja ksi|-
kowa i wiele egzemplarzy danej ksi|ki.
Fakty powy|sze wydaj si� by truizmem. Jednak przed przystpieniem do wBa[ciwego projektowa-
nia bazy danych nale|y dokona analizy rozwizywanego problemu na takim wBa[nie, podstawowym
poziomie. RozBo|enie informacji dotyczcych projektowanej aplikacji na szereg pozornie banalnych
fakt�w i ustalenie wszystkich podstawowych zwizk�w pomi�dzy jej elementami z pewno[ci uBatwi
prac� podczas tworzenia kodu programu.
Faktyczna struktura bazy danych odzwierciedla model zwizk�w encji ka|da encja odpowiada ta-
beli w bazie danych. Poni|ej przedstawiono kod w j�zyku SQL, sBu|cy do utworzenia takiej tabeli:
CREATE TABLE books (
isbn VARCHAR2(13) NOT NULL PRIMARY KEY,
title VARCHAR2(200),
summary VARCHAR2(2000),
author VARCHAR2(200),
date_published DATE,
page_count NUMBER
);
CREATE TABLE book_copies(
barcode_id VARCHAR2(100) NOT NULL PRIMARY KEY,
isbn VARCHAR2(13) NOT NULL,
CONSTRAINT book_copies_isbn_fk FOREIGN KEY (isbn) REFERENCES books (isbn)
);
Z powod�w zrozumiaBych dla specjalist�w od modelowania danych, encjom nadaje si� nazwy w for-
mie rzeczownik�w w liczbie pojedynczej (book, book_copy), natomiast tabelom w liczbie
mnogiej (books, book_copies). Ponadto warto wykona graficzn reprezentacj� tabeli na
rysunku 3.2 przedstawiono mo|liw posta zdefiniowanych tabel zapeBnionych pewnymi danymi.
Zapoznawszy si� z danymi zawartymi w tabelach, Czytelnik z pewno[ci zwr�ciB uwag� na pewne
problemy. PrzykBadowo, dane w kolumnie author s nieprawidBowe i nie jest mo|liwe poprawne
przechowanie informacji o kilku autorach jednej ksi|ki. W dalszej cz�[ci niniejszej ksi|ki zosta-
nie opisany spos�b poprawienia tych wad.
Pierwszym, przykBadowym zadaniem b�dzie utworzenie programu w j�zyku PL/SQL, kt�ry posBu-
|y do dodawania nowych ksi|ek do bazy danych. Oczywi[cie, zamiast takiego programu mo|na
po prostu wykona instrukcj� INSERT (lub dwie takie instrukcje) j�zyka SQL:
Rysunek 3.2. PrzykBad danych w postaci relacyjnej, rozbitych na wiersze i kolumny
INSERT INTO books (isbn, title, author)
VALUES ('0-596-00180-0', 'Oracle PL/SQL. Wprowadzenie',
'Bill Pribyl, Steven Feuerstein');
W zwizku z powy|szym Czytelnik z pewno[ci zastanawia si� nad sensem tworzenia programu
w j�zyku PL/SQL.
Nale|y zaBo|y, |e istnieje konieczno[ zapewnienia stosowania dw�ch sposob�w dodawania ksi-
|ek do katalogu: po pierwsze w spos�b interaktywny, poprzez r�czne wpisanie danych, po drugie
w spos�b automatyczny, pobierajc informacje o ksi|ce z innej bazy danych. Nasuwa si� zatem py-
tanie, czy w takiej sytuacji nale|y skopiowa instrukcje INSERT do dw�ch program�w. Jednak|e
p�zniej mo|e pojawi si� potrzeba napisania trzeciego programu, kt�ry dodawaBby informacje o ksi|-
kach, przykBadowo, odczytujc je z pByty CD-ROM. A zatem nale|aBoby uwzgl�dni kolejne ko-
piowanie instrukcji INSERT. ZakBadajc jednak, |e zaistnieje potrzeba zmiany struktury tabel,
trzeba by w�wczas wszystkie dotd utworzone programy oddzielnie uaktualni.
Istnieje kilka powod�w, dla kt�rych instrukcje INSERT warto umie[ci w programie PL/SQL. Poni-
|ej wymieniono najwa|niejsze z nich:
" Umo|liwia to ograniczenie, a nawet wyeliminowanie m�czcej pracy zwizanej z aktualizacj
oprogramowania po zmianie struktury bazy danych, podczas wykonywania kt�rej istnieje
mo|liwo[ popeBniania bB�d�w.
" Pozwala to na zwi�kszenie wydajno[ci dziaBania serwera bazy danych.
" Pozwala to umie[ci rozwizanie problemu programistycznego w tylko jednym miejscu.
Tworzenie poprawnych instrukcji w j�zyku SQL mo|e wymaga interpretowania oraz zapisywa-
nia w formie kodu wielu skomplikowanych reguB zarzdzania. Ewentualna konieczno[ dokonania
zmian we wszystkich napisanych programach oddzielnie oznacza bezzasadne marnotrawstwo cza-
su i wysiBku. Og�lna zasada m�wi, |e:
Instrukcje SQL nale|y umieszcza w jednym, mo|liwym do wielokrotnego wykorzystania,
programie napisanym w jzyku PL/SQL, a nie kopiowa je w wielu aplikacjach.
Nawet je[li Czytelnik jest jedynym programist w swoim miejscu pracy, powinien trzyma si� tej
zasady. Nie ogranicza si� ona zreszt tylko do wykorzystania j�zyka SQL wszelkie zadania
programistyczne powinno si� zapisywa tylko raz, a potem w razie konieczno[ci jedynie wykonywa
odpowiedni program. Przez definiowanie czynno[ci wykonywanych przez ka|d jednostk� progra-
mu, kt�r mo|na wielokrotnie wywoBywa, mo|na utworzy wBasny interfejs tworzenia oprogramo-
wania (application programming interface, API).
Tak prosty, jak to mo|liwe, ale nie prostszy
Prawdziwy bibliotekarz uznaBby niniejszy model za banalnie prosty, nawet nie biorc pod
uwag nie uwzgldnionych w nim kwestii zwizanych z czytelnikami, operacjami wypo|yczenia/
oddawania i kupowania ksi|ek. W rzeczywisto[ci funkcjonowanie biblioteki jest znacznie bar-
dziej skomplikowane:
" Poza przechowywaniem ksi|ek biblioteki magazynuj tak|e gazety i czasopisma, nagrania
muzyczne i kasety wideo.
" Wiele dzieB, na przykBad starsze ksi|ki, nie posiada numeru ISBN (International Standard
Book Number), co ogranicza jego zastosowanie jako jednoznacznego identyfikatora.
" DzieBa mog mie r�|ne tytuBy i wielu autor�w.
" Nale|y przechowywa o wiele wicej informacji: o dziaBach, wydawcach, ilustratorach,
wydaniach, dzieBach wielotomowych i pochodnych.
" Biblioteki zazwyczaj udostpniaj sobie nawzajem swoje katalogi drog elektronicznej
wymiany.
Podobnych przykBad�w jest wicej, dlatego nale|y wyja[ni powody uwzgldnienia w niniejszej
ksi|ce tak prostego przykBadu.
Wykonanie bazy danych, kt�rej schemat pokazano na rysunku 3.1, w zasadzie jest zbyt skom-
plikowanym zadaniem dla zupeBnie pocztkujcych programist�w. Relacja jeden do wielu stanowi
podstaw wikszo[ci aspekt�w projektowania baz danych (tyle |e w realnych sytuacjach chodzi
o wiele takich relacji) oraz programowania w jzyku PL/SQL. W dalszej cz[ci niniejszej ksi|ki
zostanie opisany spos�b rozszerzania funkcjonalno[ci projektowanej bazy danych, a tak|e spo-
soby wykorzystania PL/SQL w bardziej realnych zadaniach.
Innym powodem wprowadzenia pewnych uproszczeD jest fakt, |e nauka nowego materiaBu
przychodzi najBatwiej, je[li mo|na studiowa jedno zagadnienie w jednym czasie. W przeciwnym
razie nauka przychodzi du|o trudniej.
W niniejszym rozdziale przedstawiono informacje o sposobach lokalizowania kodu SQL (stosowanie
kodu w jednym miejscu) za pomoc obwolut tabel (table wrappers), kt�re s programami odpo-
wiedzialnymi za wszelkie operacje zmiany zawarto[ci ka|dej z tabel bazy danych.
Zapewne wi�kszo[ programist�w, niezale|nie od stopnia zaawansowania, odczuwa niepewno[
w sytuacji, gdy ma napisa program od podstaw. Z reguBy w takiej sytuacji mo|na rozpocz prac�
od przerabiania ju| istniejcych lub przykBadowych program�w. W tym przypadku zostanie przed-
stawiony spos�b tworzenia programu od samego pocztku, ale prawdopodobnie Czytelnik rzadko
b�dzie do tego zmuszony.
Godnym polecenia zwyczajem jest rozpocz�cie tworzenia programu od narysowania schematu. Ry-
sunek 3.3 przedstawia mo|liw reprezentacj� graficzn omawianego programu oraz jego danych wej-
[ciowych i wyj[ciowych.
Rysunek 3.3. Schemat programu sBu|cego do dodawania ksi|ek do bazy danych
W przeciwieDstwie do wcze[niej prezentowanego diagramu zwizk�w i encji, powy|szy diagram
nie zostaB skonstruowany zgodnie z jakimi[ zasadami projektowania. Najwa|niejsz rzecz jest
przedstawienie najbardziej znaczcych element�w. Z powy|szego rysunku wynika, |e trzeba skon-
struowa program zdolny do pobierania pewnych informacji, a nast�pnie do umieszczania ich w ta-
belach bazy danych. Cho zapewne nie jest to oczywiste, uwzgl�dniono mo|liwo[ poszerzenia funk-
cjonalno[ci aplikacji w przyszBo[ci.
Og�lnie rzecz biorc, jednostka programu powinna sBu|y do wykonania jednego, konkretnego
zadania i nale|y zapewni prawidBowe dziaBanie tej jednostki w swoim zakresie. Wskazane jest,
aby miaBa on niewielki rozmiar uBatwi to jej zapis i p�zniejsze modyfikacje.
Trzeba jeszcze znalez odpowiedz na pytanie, jakiej konstrukcji j�zyka PL/SQL nale|aBoby u|y
w celu zdefiniowania operacji dodawania ksi|ki add_book. Z uwagi na fakt, |e program nie b�-
dzie zwracaB |adnej warto[ci, najbardziej rozsdnym rozwizaniem jest zastosowanie procedury.
W tym podrozdziale zostanie przedstawiony spos�b napisania procedury, kt�ra ma wstawia infor-
macje na temat danej ksi|ki do bazy danych. Procedura taka mo|e by nazwana obwolut. Mo|na
te| powiedzie, u|ywajc terminologii pochodzcej z j�zyka greckiego, |e b�d wykorzystywane
abstrakcje (abstraction), procesy enkapsulacji (encapsulation) oraz ukrywania informacji (informa-
tion hiding) definicje wymienionych poj� znajduj si� w SBowniczku. Na rysunku 3.4 przedsta-
wiono wi�cej szczeg�B�w dotyczcych takiego rozwizania.
Rysunek 3.4. Jedynie z poziomu programu PL/SQL bdzie mo|liwe dodawanie informacji o ksi|ce do bazy danych
U|ytkownicy gotowego programu nie musz wiedzie na jego temat zbyt wiele, jednak tw�rca danej
aplikacji musi z pewno[ci posiada gruntown wiedz� dotyczc struktury bazy danych. Dlatego
te| pierwsz rzecz, jak nale|y wykona, jest okre[lenie tabel i ich kolumn zwizanych z procesem
wykonania reguBy zarzdzania (w tym przypadku dodania ksi|ki). Trzeba odpowiedzie sobie na
pytanie, jakie informacje s potrzebne do manipulowania zawarto[ci tych tabel.
W celu okre[lenia istotnych dla wykonania planowanej operacji tabel i kolumn trzeba przyjrze si�
projektowi bazy danych (przedstawionemu we wcze[niejszej cz�[ci niniejszego rozdziaBu). List� tych
kolumn mo|na z Batwo[ci utworzy za pomoc instrukcji DESCRIBE, dost�pnej w SQL*Plus (w for-
mie skr�conej DESC):
SQL> DESC ksiazki
Name Null? Type
-------------------------------------------- -------- -----------------------
ISBN NOT NULL VARCHAR2(13)
TITLE VARCHAR2(200)
SUMMARY VARCHAR2(2000)
AUTHOR VARCHAR2(200)
DATE_PUBLISHED DATE
PAGE_COUNT NUMBER
SQL> DESC egzemplarze_ksiazki
Name Null? Type
-------------------------------------------- -------- -----------------------
BARCODE_ID NOT NULL VARCHAR2(100)
ISBN VARCHAR2(13)
Po przeanalizowaniu listy kolumn mo|na przyj, |e wi�kszo[ zawartych w nich informacji powin-
na by znana osobie wykonujcej katalogowanie i dlatego nie trzeba niczego syntetyzowa, spraw-
dza lub oblicza. Procedura b�dzie wi�c bardzo prosta.
Podstawowym problemem do rozwizania jest podj�cie decyzji, czy u|ytkownik b�dzie wstawiaB
dane do obydw�ch tabel jednocze[nie, czy te| oddzielnie. Na tym etapie pracy odpowiedz na to
pytanie jest jeszcze nieznana. Najprawdopodobniej w bibliotekach odbywa si� to w ten spos�b, |e
informacje o ksi|kach s dodawane do bazy danych w momencie pojawienia si� pierwszego eg-
zemplarza. Dlatego te| podczas dodawania danej ksi|ki po raz pierwszy wszystkie informacje
wymagane dla wypeBnienia obydw�ch tabel s od razu znane: od numeru ISBN po identyfikator
kodu kreskowego. Jednak istnieje tak|e konieczno[ katalogowania nowych egzemplarzy ksi|ki
ju| znajdujcej si� w zbiorach biblioteki t� potrzeb� r�wnie| nale|y uwzgl�dni podczas pla-
nowania programu.
Rozpoczynajc opracowywanie nowego projektu wielu programist�w zapisuje tzw. pseudokod
w postaci zwykBych zdaD, kt�re opisuj z grubsza dziaBanie programu. W tym przypadku mo|na
by napisa:
Sprawdz, czy dane wej[ciowe s prawidBowe.
Wstaw nowy rekord do tabeli "books".
Wstaw nowy rekord do tabeli "book_copies".
Kolejnym etapem b�dzie przedstawienie skBadni konstrukcji j�zykowych potrzebnych do utworze-
nia procedury. Nast�pnie zapisany pseudokod zostanie zamieniony na konkretne instrukcje.
Poni|ej znajduje si� opis r�|nych cz�[ci skBadowych procedury. Zazwyczaj procedury tworzy si� za
pomoc instrukcji o nast�pujcej skBadni:
CREATE [ OR REPLACE ] PROCEDURE nazwa_procedury
(parametr1 TRYB TYP_DANYCH [ DEFAULT wyra|enie ],
parametr2 TRYB TYP_DANYCH [ DEFAULT wyra|enie ],
...)
AS
[ zmienna1 TYP_DANYCH;
zmienna2 TYP_DANYCH;
... ]
BEGIN
instrukcje_wykonawcze
[ EXCEPTION
WHEN nazwa_wyjtku
THEN
instrukcje_wykonawcze ]
END;
/
Powy|szy wzorzec zawiera kombinacj� sB�w kluczowych j�zyka PL/SQL (pisane du|ymi literami
i nie kursyw) oraz wyra|eD do zastpienia (pisane kursyw) w kodzie tworzonego programu.
CREATE [ OR REPLACE ]
Jest to szczeg�lna instrukcja SQL, sBu|ca do utworzenia procedury. Fraza OR REPLACE (lub
zastp) jest opcjonalna i pozwala na unikni�cie konieczno[ci usuwania ju| istniejcej procedury
w przypadku tworzenia jej nowej wersji. Zastosowanie wyra|enia OR REPLACE zachowuje
tak|e wszelkie synonimy (synonyms) oraz granty (grants), jakie zostaBy uprzednio utworzone,
a s zale|ne od dziaBania procedury. Jest to du|a zaleta.
PROCEDURE nazwa_procedury
W sekcji nagB�wka podaje rodzaj tworzonej jednostki programowej (w tym wypadku procedura)
oraz nadaje si� jej nazw�.
parametr1 TRYB TYP_DANYCH [ DEFAULT wyra|enie ]
Aby umo|liwi u|ytkownikowi podawanie parametr�w wywoBania procedury, nale|y utworzy
list� definicji parametr�w oddzielonych przecinkami, a caB list� obj w nawiasy. TRYB mo|e
mie warto[: IN, OUT lub IN OUT. Poni|ej znajduje si� opis wszystkich opcji.
IN
SBowo kluczowe oznaczajce tryb tylko do odczytu. WywoBujcy procedur� podaje warto[
parametru, a PL/SQL nie pozwala na jej zmian� wewntrz programu.
OUT
SBowo kluczowe oznaczajce tryb tylko do zapisu. Oznacza to, |e procedura nadaje
parametrowi pewn warto[, kt�ra jest odczytywana przez program wywoBujcy. Podanie
jakiejkolwiek warto[ci takiego parametru podczas wywoBania procedury jest ignorowane.
IN OUT
SBowo kluczowe oznaczajce tryb do odczytu lub zapisu. SBowo to jest u|ywane w sytuacji,
gdy warto[ zmiennej, przekazywanej do procedury jako parametr, ma by zar�wno
odczytywana, jak i zmieniana, a nast�pnie zwracana do programu wywoBujcego.
TYP_DANYCH
Znaczenie tego parametru przedstawiono w rozdziale 2. dopuszczalnymi warto[ciami s
na przykBad: NUMBER, INTEGER, VARCHAR2, DATE. Jedyna r�|nica polega na tym,
|e w tym miejscu nale|y poda jedynie rodzaj typu, bez jego dokBadnej specyfikacji. Innymi
sBowy, nale|y u|y VARCHAR2 zamiast VARCHAR2(30) i NUMBER zamiast NUMBER(10,2).
DEFAULT wyra|enie
Pozwala na przypisanie parametrowi warto[ci domy[lnej w przypadku, gdy wywoBanie procedury
jej nie okre[la. Mo|na tak|e u|y symbolu := (dwukropek i znak r�wno[ci) zamiast sBowa
kluczowego DEFAULT.
AS
SBowo kluczowe AS oddziela nagB�wek od reszty jednostki programowej. Opcjonalnie mo|na
u|y sBowa kluczowego IS, kt�re jest r�wnowa|ne AS.
BEGIN..END
SBowa BEGIN i END oddzielaj zwykBe, czyli wykonawcze instrukcje od reszty programu.
EXCEPTION
Oznacza pocztek kodu obsBugi wyjtku tej cz�[ci programu, kt�ra jest wykonywana tylko
w przypadku przechwycenia wyjtku w sekcji wykonawczej. Wszystkie elementy umieszczone
po sBowie kluczowym EXCEPTION i przed instrukcj END s cz�[ci obsBugi wyjtku.
WHEN nazwa_wyjtku THEN instrukcje_wykonawcze
Mo|liwym do wystpienia sytuacjom bB�dnego dziaBania programu zazwyczaj s nadawane
nazwy albo przez system Oracle, albo przez programist�. Dzi�ki temu mo|na w kodzie
programu zapisa instrukcje wychwytujce te sytuacje i umo|liwi odpowiedni na nie
reakcj�, kt�r jest wykonanie pewnego fragmentu kodu. Je[li taka nazwa jest nieznana lub
w celu wychwytywania bB�d�w, kt�re nie zostaBy nazwane, mo|na posBu|y si� sBowem
OTHERS, kt�re dotyczy wszystkich sytuacji wyjtkowych. W zapisie wygldaBoby
to nast�pujco: WHEN OTHERS THEN....
Pewne elementy kodu procedury s opcjonalne. Najprostsza, mo|liwa do utworzenia procedura po-
siada nast�pujc form�:
CREATE PROCEDURE nie_rob_nic AS
BEGIN
NULL;
END;
Z powy|szego wynika, |e parametry, zmienne i kod obsBugi wyjtk�w s opcjonalne. SBowo kluczowe
NULL zostaBo tutaj zastosowane jako instrukcja wykonawcza. Oznacza ona tyle, co nie r�b nic .
Korzystajc z potrzebnych element�w podanego wcze[niej wzorca mo|na zapisa pseudokod w for-
mie prawdziwego kodu:
CREATE OR REPLACE PROCEDURE add_book (isbn_in IN VARCHAR2,
barcode_id_in IN VARCHAR2, title_in IN VARCHAR2, author_in IN VARCHAR2,
page_count_in IN NUMBER, summary_in IN VARCHAR2 DEFAULT NULL,
date_published_in IN DATE DEFAULT NULL)
AS
BEGIN
/* sprawdzenie poprawno[ci danych wej[ciowych */
IF isbn_in IS NULL
THEN
RAISE VALUE_ERROR;
END IF;
/* wstawienie rekordu do tabeli "books" */
INSERT INTO books (isbn, title, summary, author, date_published,
page_count)
VALUES (isbn_in, title_in, summary_in, author_in, date_published_in,
page_count_in);
/* je[li to konieczne, wstawienie rekordu do tabeli "book_copies" */
IF barcode_id_in IS NOT NULL
THEN
INSERT INTO book_copies (isbn, barcode_id)
VALUES (isbn_in, barcode_id_in);
END IF;
END add_book;
/
Poni|ej znajduje si� opis dziaBania utworzonej procedury.
Nazwa procedury i kolejno[ parametr�w. Nazw procedury jest wyra|enie czasownikowe, kt�re
opisuje dziaBanie tej procedury. Podano tu tak|e parametry wej[ciowe na ka|d z kolumn tabel,
do kt�rych maj by wprowadzane dane, przypada jeden parametr. W celu wyeksponowania naj-
wa|niejszych parametr�w (isbn_in czy barcode_id_in) oraz w celu umieszczenia parame-
tr�w o warto[ciach domy[lnych na koDcu, zmieniono nieco ich kolejno[ w odniesieniu do kolej-
no[ci kolumn w tabelach.
Nazwy parametr�w. Warto przyj pewn konwencj� nazewnictwa w programowaniu i do nazw
parametr�w doda si� nazw� ich trybu (IN, OUT lub IN OUT). Poniewa| wszystkie parametry
procedury add_book s parametrami w trybie IN, ich nazwy zawieraj koDc�wk� _in. Taka
konwencja nadawania nazw nie jest obowizkowa, ale jest pomocna w unikaniu konflikt�w z na-
zwami kolumn podczas u|ywania instrukcji SQL. Gdyby pozostaBy one identyczne, otrzymana in-
strukcja miaBaby nast�pujc posta:
INSERT INTO book_copies (barcode_id, isbn)
VALUES (barcode_id, isbn);
W takim przypadku odr�|nianie nazwy kolumn od nazw zmiennych podczas odczytywania kodu
mogBoby okaza si� problematyczne nawet dla do[wiadczonego programisty. Jednak|e sama in-
strukcja zostaBaby wykonana prawidBowo, gdy| PL/SQL zinterpretowaBby wszystko nast�pujco:
INSERT INTO book_copies (barcode_id, isbn) /* nazwy kolumn */
VALUES (barcode_id, isbn); /* zmienne PL/SQL */
Jednak|e instrukcja:
UPDATE ksiazki
SET summary = summary /* BBd! */
WHERE isbn = isbn; /* Nie wolno tak robi! */
nie zostanie wykonana prawidBowo. PL/SQL zinterpretuje ka|de wystpienie summary oraz isbn
jako nazwy kolumn.
Weryfikacja danych wej[ciowych. Zapis pierwszej linii zaprezentowanego wcze[niej pseudoko-
du m�wiB: Sprawdz, czy dane wej[ciowe s prawidBowe . Konieczne jest jednak podj�cie jeszcze
kilku ustaleD. PrzykBadowo, mo|na zaBo|y, |e u|ytkownicy systemu b�d domaga si� minimalnych
wymagaD ze strony procedury w momencie jej wywoBywania. Mo|e to oznacza, |e jedynym ab-
solutnie wymaganym parametrem tworzonej procedury jest ISBN. Std te| sekcja weryfikacji da-
nych wej[ciowych zostaBa zapisana jako:
IF isbn_in IS NULL
THEN
RAISE VALUE_ERROR;
END IF;
Bez dokBadniejszej znajomo[ci powy|szych identyfikator�w nie jest mo|liwe przeprowadzenie bar-
dziej wymy[lnej weryfikacji poprawno[ci danych wej[ciowych. Przedstawiony wy|ej fragment kodu
oznacza, |e brak ISBN powoduje zatrzymanie wykonywania programu.
W dalszej cz�[ci kodu jest tak|e wykonywane sprawdzenie kodu kreskowego. Program zostaB skon-
struowany w ten spos�b, aby unikn wykonania niepoprawnej instrukcji INSERT, co spowodo-
waBoby bBd.
W rozdziale 2. wyja[niono, |e w razie wystpienia bB�du PL/SQL zatrzymuje wykonywanie progra-
mu za pomoc mechanizmu zwanego przechwytywaniem wyjtku (raising an exception). Jak wy-
nika z rysunku 3.5, instrukcja:
RAISE VALUE_ERROR
zatrzymuje wykonywanie instrukcji sekcji wykonawczej i przekazuje sterowanie do kodu obsBugi
wyjtku. Je[li taki kod nie istnieje, wyjtek zwraca pewien bBd do programu wywoBujcego, a ten
reaguje w okre[lony przez programist� spos�b.
Rysunek 3.5. Prosty przykBad obsBugi wyjtku
Wyjtek VALUE_EXCEPTION nale|y do grupy wyjtk�w wewn�trznych, kt�re w pewnych sytu-
acjach s przechwytywane przez system Oracle. Program wywoBujcy procedur� add_book po-
winien umo|liwia obsBug� wszelkich mo|liwych do przewidzenia wyjtk�w i na podstawie infor-
macji dotyczcych napotkanego bB�du zdecydowa o dalszym funkcjonowaniu programu. W tym
przypadku po|danym dziaBaniem byBoby przerwanie procesu dodawania do bazy danych niekom-
pletnych informacji. Najlepiej byBoby, gdyby program wywoBujcy zwracaB u|ytkownikowi infor-
macj� o bB�dzie.
By mo|e Czytelnik zastanawia si� na celowo[ci podejmowania takich dziaBaD zamiast, przykBa-
dowo, umo|liwienia samej procedurze add_book wy[wietlania komunikatu o napotkanym bB�-
dzie. Celowo[ u|ycia mechanizmu wyjtk�w staje si� jasna po u[wiadomieniu sobie, |e przeka-
zanie obsBugi sytuacji wyjtkowych do procedury ograniczyBoby w znacznym stopniu mo|liwo[ci jej
ponownego wykorzystania. Je[li procedura add_book obsBuguje wyjtek i wy[wietla komunikat
o bB�dzie, niemo|liwe jest wykorzystanie jej przez program, dla kt�rego dziaBania takie komuni-
katy s niewskazane. PrzykBadowo, mo|na zaBo|y istnienie programu, kt�ry odczytuje informacje
o ksi|kach z pliku i jednorazowo wprowadza do bazy danych informacje dotyczce tysi�cy ksi|ek.
Program ten ma wywoBywa procedur� add_book dla ka|dej kolejnej pozycji i w razie wyst-
pienia bB�du zapami�ta informacj� o jego przyczynie, nie przerywajc jednak swojego dziaBania,
a| do zakoDczenia wprowadzania danych dotyczcych ostatniej ksi|ki. Dopiero w�wczas mo|na
by przedstawi u|ytkownikowi podsumowanie informacji o napotkanych problemach. Wykorzysta-
nie procedury add_book w taki spos�b jest mo|liwe jedynie poprzez propagacj� wyjtk�w na ze-
wntrz do programu wywoBujcego.
Uog�lniajc, je[li istnieje prawdopodobieDstwo napotkania przez program bB�du, kt�rego
nie da si� naprawi w prosty spos�b, nale|y zapewni mo|liwo[ przechwycenia wyjtku.
W dalszej cz�[ci niniejszej ksi|ki opisano wyjtki, kt�re nale|y bra pod uwag�.
Je|eli weryfikacja poprawno[ci danych wej[ciowych przebiega pomy[lnie, program kontynuuje swoje
dziaBanie wykonujc instrukcje INSERT j�zyka SQL. Nie ma potrzeby zwracania jakichkolwiek
danych do programu wywoBujcego. Jednak gdyby zaszBa taka konieczno[, mo|na uwzgl�dni
jedn z dw�ch mo|liwo[ci: zastosowanie funkcji zamiast procedury lub wykorzystanie parametr�w
w trybie OUT. Wi�cej informacji Czytelnik znajdzie w dalszej cz�[ci niniejszego rozdziaBu.
NajBatwiejszym sposobem wywoBania procedury z poziomu kodu PL/SQL jest napisanie jej nazwy
wraz z potrzebnymi argumentami, umieszczonymi w nawiasach i oddzielonymi przecinkami:
BEGIN
nazwa_procedury (argument1, argument2, ...);
END;
PrzykBadowo, aby doda do katalogu now ksi|k�, nale|y napisa:
BEGIN
add_book('1-56592-335-9',
'100000001',
'Programowanie w Oracle PL/SQL',
'Feuerstein, Steven, Bill Pribyl',
987,
'Kompendium informacji o jzyku PL/SQL, '
|| 'wraz z przykBadami i poradami na temat programowania.',
TO_DATE('01-WRZ-1997','DD-MON-YYYY'));
END;
/
Takie wywoBanie procedury spowoduje wstawienie po jednym rekordzie do tabel books oraz book_
copies. W powy|szym przykBadzie argumentami s tak zwane wyra|enia literalne, a PL/SQL
przekazuje te warto[ci do programu jako parametry wej[ciowe1, zgodnie z ich kolejno[ci. Ozna-
cza to, |e zazwyczaj warto[ci trzeba podawa w takiej samej kolejno[ci, w jakiej wyst�puj parame-
try w programie wywoBywanym. Informacje te przedstawiono w poni|szej tabeli:
1
Wyra|enie przekazywane przez program wywoBujcy nosi nazw� argumentu lub parametru aktualnego,
podczas gdy zmienne zdefiniowane w nagB�wku programu wywoBujcego s nazywane parametrami
formalnymi lub po prostu parametrami. W tym kontek[cie formalny oznacza formujcy posta zmiennej.
Pozycja Nazwa parametru Typ danych Warto[ u|yta w przykBadowym wywoBaniu
parametru
isbn_in '1-56592-335-9'
1 VARCHAR2
barcode_id_in '100000001'
2 VARCHAR2
title_in 'Programowanie w Oracle PL/SQL'
3 VARCHAR2
author_in 'Feuerstein, Steven, Bill Pribyl'
4 VARCHAR2
page_count_in 987
5 NUMBER
summary_in 'Kompendium informacji o jzyku
6 VARCHAR2
PL/SQL wraz z przykBadami i poradami
na temat programowania.'
date_published_in TO_DATE('01-WRZ-1997','DD-MON-YYYY')
7 DATE
Warto zwr�ci uwag�, |e podane warto[ci s zgodne z typami danych, jakich wymaga procedura.
Oznacza to, |e ka|demu parametrowi typu VARCHAR2 odpowiada cig znakowy, parametrowi typu
NUMBER odpowiada seria cyfr. Czytelnik zapewne zauwa|yB, |e parametrowi typu DATE odpo-
wiada warto[ o do[ dziwnym wygldzie.
Parametr date_published_in wymaga podania warto[ci typu DATE systemu Oracle. W rze-
czywisto[ci jest to seria bit�w o skomplikowanym formacie wewn�trznym z pewno[ci nie jest
to zwykle u|ywana kombinacja roku, miesica i dnia. Cz�sto stosowan metod otrzymania takiej
warto[ci jest wykorzystanie wewn�trznej funkcji systemu Oracle o nazwie TO_DATE. Podczas
wywoBywania tej funkcji nale|y poda dat�, zapisan w formie cigu znakowego (w tym przypadku
'01-WRZ-1997'), oraz dodatkowy element, zwany mask formatu (format mask) 'DD-
-MON-YYYY'. Funkcja TO_DATE pr�buje dopasowa do siebie poszczeg�lne elementy wyspecy-
fikowanego cigu znak�w z odpowiednimi elementami maski formatujcej. W przypadku pomy[l-
nego wykonania funkcja TO_DATE zwraca warto[ binarn, kt�r system Oracle rozpoznaje jako
warto[ typu DATE. W przeciwnym przypadku nast�puje przechwycenie wyjtku.
Wr�my do omawianego przykBadu: funkcja TO_DATE przekazuje wspomnian warto[ binarn
jako argument do procedury add_book. Dla tej procedury spos�b utworzenia warto[ci typu
DATE jest bez znaczenia bezpo[rednie podawanie warto[ci literaB�w jest r�wnie dobrym roz-
wizaniem, co uwzgl�dnienie wyniku dziaBania funkcji, takiej jak na przykBad TO_DATE.
Zastosowanie funkcji TO_DATE nie zawsze jest konieczne, poniewa| system Oracle
automatycznie podejmuje pr�b� konwersji cigu znakowego na dat�. W sytuacji takiej trzeba
opiera si� na domy[lnej masce formatu systemu Oracle, kt�ra mo|e zosta zmieniona przez
administratora bazy danych. Zwi�ksza to prawdopodobieDstwo wystpienia pewnych
problem�w, jak na przykBad interpretacja warto[ci roku (jaki rok jest oznaczony warto[ci '00'?).
Og�lnie mo|na powiedzie, |e w celu konwersji na format daty systemu Oracle nale|y
skorzysta z funkcji TO_DATE.
Powy|szy fragment kodu zawiera argumenty podane w formie literaB�w (literals), to znaczy z za-
stosowaniem konkretnych warto[ci. Jest to dobry spos�b w przypadku przeprowadzania test�w,
jednak|e podczas programowania w j�zyku PL/SQL zazwyczaj u|ywa si� zmiennych w wywoBa-
niach. Warto[ci zmiennych s zazwyczaj ustalane nie poprzez bezpo[redni zapis w kodzie programu,
ale na przykBad przez u|ytkownika korzystajcego z klawiatury i ekranu, wy[wietlajcego odpowied-
nie informacje.
Warto si� zastanowi nad sposobem wywoBywania procedury w przypadku posiadania niepeBnej
informacji dotyczcej dodawanej ksi|ki na przykBad w przypadku braku daty wydania lub opisu.
PrzykBadowo, w takim przypadku mo|na poda warto[ci NULL dla tych parametr�w i sprawdzi, czy
nie spowoduje to problem�w z wykonywaniem programu:2
add_book('1-56592-335-9', '100000001', 'Programowanie w Oracle PL/SQL',
'Feuerstein, Steven, Bill Pribyl', 987, NULL, NULL);
Jest to jedna z mo|liwo[ci. Mo|na tak|e w og�le nie podawa warto[ci argument�w i oprze si� na
warto[ciach domy[lnych. W tym przypadku b�dzie to wywoBanie poprawne, gdy| w sekcji nagB�w-
kowej procedury dla dw�ch ostatnich parametr�w zdefiniowano warto[ci domy[lne:
...summary_in IN VARCHAR2 DEFAULT NULL,
date_published_in IN DATE DEFAULT NULL);
Warto[ci NULL w tym kontek[cie s w peBni poprawnymi warto[ciami.
Korzystajc z warto[ci domy[lnych, mo|na przedstawione powy|ej wywoBanie upro[ci i pomin
ostatnie dwa argumenty:
add_book('1-56592-335-9', '100000001', 'Programowanie w Oracle PL/SQL',
'Feuerstein, Steven, Bill Pribyl', 987);
W tym przypadku mechanizm odpowiedzialny za wykonanie kodu PL/SQL w miejsce brakujcych
argument�w podstawi warto[ci domy[lne i wykonanie procedury odb�dzie si� identycznie, jak we
wcze[niejszym przypadku.
Mo|liwo[ pomijania argument�w dla parametr�w posiadajcych warto[ domy[ln jest
niezwykle przydatn cech j�zyka PL/SQL, poniewa| umo|liwia prawidBowe dziaBanie
jednostki programowej nawet bez podania tych argument�w.
Ponadto mechanizm ten mo|e w ogromnym stopniu zredukowa negatywny wpByw
ewentualnych, przyszBych modyfikacji. PrzykBadowo, je[li zaistnieje potrzeba dodania
do programu pewnych parametr�w, to dzi�ki zdefiniowaniu ich warto[ci domy[lnych nie
b�dzie trzeba przeglda caBego kodu, aby zmieni ka|de wyst�pujce w nim wywoBanie.
2
Ze wzgl�du na oszcz�dno[ miejsca w niniejszej ksi|ce nie zawsze jest przedstawiany peBny kod programu.
W tym przypadku nale|aBoby doda instrukcj� EXECUTE lub obj wywoBanie sBowami kluczowymi
BEGIN i END oraz doda koDcowe / w celu uruchomienia tej procedury z poziomu SQL*Plus.
Warto te| wiedzie, |e wywoBujc procedur� mo|na jednocze[nie pomija parametry posiadajce
warto[ci domy[lne oraz podawa warto[ci NULL:
add_book('1-56592-335-9', '100000001', 'Programowanie w Oracle PL/SQL', NULL,
987);
Czytelnik by mo|e ma pewne problemy z zapami�taniem, kt�ra warto[ odpowiada kt�remu ar-
gumentowi, ale jest to rzecz normalna w przypadku notacji pozycyjnej (positional notation), co ozna-
cza konieczno[ podawania argument�w w takiej samej kolejno[ci, w jakiej zapisano dane parametry
w kodzie programu.
Rozwizaniem tych problem�w mo|e by zastosowanie innego, bardzo u|ytecznego mechanizmu
notacji imiennej (named notation). Spos�b dziaBania notacji imiennej najlepiej mo|na wyja[ni
na przykBadzie. W przypadku poni|szego wywoBania procedury add_book wykorzystano wBa[nie
ten mechanizm:
add_book(isbn_in => '1-56592-335-9',
title_in => 'Programowanie w Oracle PL/SQL',
summary_in => 'Kompendium informacji o jzyku PL/SQL, ' ||
'wraz z przykBadami i poradami na temat programowania.',
author_in => 'Feuerstein, Steven, Bill Pribyl',
date_published_in => NULL,
page_count_in => 987,
barcode_id_in => '100000001');
Z powy|szego wynika, |e dla ka|dego argumentu podaje si� nazw� parametru zdefiniowanego w pro-
cedurze add_book, symbol => oraz warto[ danego parametru. Zalet tej metody jest to, |e po-
szczeg�lne argumenty mo|na podawa w dowolnej kolejno[ci nie trzeba pami�ta kolejno[ci,
w jakiej zdefiniowano parametry w procedurze.
Wyb�r metody caBkowicie zale|y od programisty dla kompilatora jest to bez znaczenia. Argu-
mentem przemawiajcym za stosowaniem notacji imiennej mo|e by fakt, |e w ten spos�b kod staje
si� du|o bardziej przejrzysty. Znaczenie wyra|enia page_count => 987 nie pozostawia wt-
pliwo[ci, a na pewno nie jest tak w przypadku podania samej warto[ci 987. Mo|na tak|e, oczywi-
[cie, pomija parametry opcjonalne (domy[lne) w tym przypadku mo|e to by, przykBadowo,
date_published_in:
add_book(isbn_in => '1-56592-335-9',
title_in => 'Programowanie w Oracle PL/SQL',
summary_in => 'Kompendium informacji o jzyku PL/SQL, ' ||
'wraz z przykBadami i poradami na temat programowania.',
author_in => 'Feuerstein, Steven, Bill Pribyl',
page_count_in => 987,
barcode__is_in => '100000001');
Poza konieczno[ci pisania wi�kszej ilo[ci kodu istnieje tak|e pewna niedogodno[, wynikajca ze
stosowania tej notacji. W razie potrzeby zmiany nazwy parametru konieczne jest uaktualnienie nie
tylko samej procedury, ale tak|e ka|dego jej wywoBania w notacjiimiennej. Z drugiej jednak stro-
ny zmiana nazwy parametru jest raczej rzadko wykonywan operacj.
Istnieje tak|e mo|liwo[ wykorzystania obydw�ch notacji w jednym wywoBaniu. Nale|y pami�ta
jedynie o paru zasadach. Nale|y zacz od notacji pozycyjnej, a po przej[ciu do notacji imiennej
trzeba przy niej pozosta do koDca. Oto przykBad:
add_book('1-56592-335-9', '100000001',
'Programowanie w Oracle PL/SQL',
summary_in => NULL, author_in => 'Feuerstein, Steven, Bill Pribyl',
page_count_in => 987);
U|ywanie notacji imiennej
W razie konieczno[ci dokonania wyboru nale|y stosowa notacj wymieniajc wszdzie tam,
gdzie znaczenie poszczeg�lnych argument�w nie jest oczywiste. PrzykBadowo:
uaktualnij_moj_profil(ulub_ksiazka_isbn => '1-56592-335-9');
Notacji pozycyjnej nale|y u|ywa w przypadku czsto u|ywanych program�w u|ytkowych,
kt�re posiadaj jeden lub dwa parametry, a znaczenie tych parametr�w jest oczywiste:
DBMS_OUTPUT.PUT_LINE('Witaj Muddah.');
Zastosowanie obydw�ch notacji mo|e okaza si przydatne w sytuacji, gdy na przykBad
pierwszy argument jest oczywisty, za[ kolejne nie:
moje_put_line('Witaj Fadduh.', linie_do_pominiecia => 2);
W tym podrozdziale przedstawiono przykBad konstruowania i wykorzystywania procedury magazy-
nowanej j�zyka PL/SQL, kt�ra wykonuje pojedyncze zadanie. Zadanie to polega na dodaniu do bazy
danych informacji o ksi|ce identyfikowanej za pomoc odpowiedniego kodu kreskowego. Kolej-
ne zadanie polega na okre[leniu liczby egzemplarzy danej ksi|ki. Potrzeba pobierania informacji
o takiej pojedynczej warto[ci stanowi idealn sposobno[ wykorzystania funkcji j�zyka PL/SQL,
kt�ra ze swej definicji zwraca jak[ warto[ (lub koDczy dziaBanie nie obsBu|onym wyjtkiem).
Przed podj�ciem pr�by zapisania kodu funkcji trzeba najpierw zapozna si� z og�ln skBadni two-
rzenia funkcji. Funkcje stanowi drugi typ program�w magazynowanych.
Poni|ej przedstawiono wzorzec definiowania funkcji. Elementy, kt�re oznaczono za pomoc czcion-
ki pogrubionej, mog by jeszcze Czytelnikowi nieznane.
CREATE [ OR REPLACE ] FUNCTION nazwa_funkcji
(parametr1 TRYB TYP_DANYCH [ DEFAULT wyra|enie ],
parametr2 TRYB TYP_DANYCH [ DEFAULT wyra|enie ],
...)
RETURN TYP_DANYCH
AS
[ zmienna1 TYP_DANYCH;
zmienna2 TYP_DANYCH;
... ]
BEGIN
instrukcje_wykonawcze;
RETURN wyra|enie;
[ EXCEPTION
WHEN nazwa_wyjtku
THEN
instrukcje_wykonawcze ]
END;
/
R�|nice pomi�dzy wzorcem dotyczcym funkcji i wzorcem procedury s minimalne. Poza zamian
sBowa kluczowego PROCEDURE na FUNCTION w instrukcji CREATE, kod r�|ni si� tylko w dw�ch
miejscach. Pierwszym z nich jest nagB�wek, gdzie podaje si� zwracany typ danych, a drugim jest
cz�[ wykonawcza, gdzie nast�puje bezpo[rednie przekazanie zwracanej warto[ci do programu wy-
woBujcego.
RETURN TYP_DANYCH
W nagB�wku wyra|enie RETURN stanowi cz�[ deklaracji funkcji. Jest to informacja o typie
danych warto[ci, kt�re maj by zwracane w wyniku wywoBania funkcji.
RETURN wyra|enie
Wewntrz sekcji wykonawczej wyra|enie RETURN jest instrukcj i oznacza, |e dziaBania zostaBy
zakoDczone i |e nale|y zwr�ci (return) warto[, kt�r definiuje wyra|enie. Instrukcja RETURN
mo|e znalez si� tak|e w sekcji EXCEPTION.
Obydwie wymienione instrukcje s wymagane. W nast�pnym podrozdziale przedstawiono kod go-
towej funkcji.
Funkcja book_copy_qty zwraca liczb� ksi|ek, kt�rych numer ISBN odpowiada podanemu.
W poni|szym, przykBadowym kodzie funkcji do pobrania danych z bazy danych wykorzystano
kursor (cursor). Szczeg�Bowe om�wienie tej struktury znajduje si� dopiero w rozdziale 5. Uog�lnia-
jc, kursor jest okre[lonym miejscem w pami�ci, do kt�rego program mo|e przenie[ pewne dane po-
brane z bazy danych. W sekcji deklaracji nast�puje powizanie pewnej instrukcji SELECT z kur-
sorem. Powizanie to zachodzi za pomoc instrukcji CURSOR. Warto zwr�ci uwag�, |e parametr
wej[ciowy isbn_in wyst�puje po prawej stronie wyra|enia WHERE. W celu pobrania danych nale-
|y kursor otworzy (open), pobra (fetch) z niego dane, a w koDcu go zamkn (close).
CREATE OR REPLACE FUNCTION book_copy_qty(isbn_in IN VARCHAR2)
RETURN NUMBER
AS
number_o_copies NUMBER := 0;
CURSOR bc_cur IS
SELECT COUNT(*)
FROM book_copies
WHERE isbn = isbn_in;
BEGIN
IF isbn_in IS NOT NULL
THEN
OPEN bc_cur;
FETCH bc_cur INTO number_o_copies;
CLOSE bc_cur;
END IF;
RETURN number_o_copies;
END;
/
Konstrukcja funkcji niewiele odbiega od procedury. R�|ni si� one jednak swoim zachowaniem
szczeg�By dotyczce dziaBania funkcji przedstawiono na rysunku 3.6.
Rysunek 3.6. Wykorzystanie funkcji jzyka PL/SQL w celu zwr�cenia pewnej warto[ci do programu wywoBujcego; dla danej warto[ci
ISBN funkcja zwraca liczb egzemplarzy znajdujcych si w bazie danych
Zasadnicza r�|nica pomi�dzy wywoBaniem funkcji i procedury wynika z tego, |e funkcje zwracaj
pewn warto[.
Najprostszym sposobem wykorzystania warto[ci wynikowej, zwracanej przez funkcj�, jest jej przy-
pisanie do pewnej zmiennej, kt�rej typ odpowiada typowi zwracanej warto[ci. Zwykle wyglda to
w nast�pujcy spos�b:
DECLARE
zmienna_lokalna TYP_DANYCH;
BEGIN
zmienna_lokalna := nazwa_funkcji (argument1, argument2, ...);
END;
/
Jest to zatem typowa instrukcja przypisania, gdzie wywoBanie funkcji znajduje si� po prawej stronie
operatora przypisania, a zmienna lokalna po lewej. Mo|na wi�c napisa:
DECLARE
ile INTEGER;
BEGIN
ile := book_copy_qty('1.56592-335-9');
END;
/
Z informacji przedstawionych w rozdziale 1. wynika, |e w celu wy[wietlenia wynik�w na ekranie
mo|na przekaza je do funkcji DBMS_OUTPUT.PUT_LINE:
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE('Liczba kopii 1-56592-335-9: '
|| book_copy_qty('1-56592-335-9'));
END;
/
Funkcja book_copy_qty zwraca warto[ typu VARCHAR2, co umo|liwia konkatenacj� z innym
cigiem znak�w i u|ycie funkcji PUT_LINE. Takie zagnie|d|anie funkcji wewntrz innych in-
strukcji jest cz�sto stosowan technik.
Poni|ej wymieniono kilka wartych zapami�tania zasad dotyczcych wykorzystania funkcji:
1. Nie mo|na tworzy niezale|nych (standalone) funkcji o takich samych nazwach, jakie nosz
niezale|ne procedury. Jednak|e przyj�cie konwencji nazywania procedur wyra|eniem
czasownikowym, a funkcji wyra|eniem rzeczownikowym mo|e uchroni przed potencjalnymi
problemami.
2. Nieuwzgl�dnienie w nagB�wku wyra|enia RETURN spowoduje, |e funkcja nie zostanie
skompilowana. Jest to dziaBanie pozytywne, gdy| bB�dy czasu kompilacji uwa|a si� za metod�
wczesnego ostrzegania przed ewentualnymi problemami. Je[li jednak sBowo kluczowe RETURN
zostanie pomini�te w sekcji wykonawczej, system Oracle poinformuje o tym dopiero po
uruchomieniu funkcji. Zostanie wtedy wygenerowany komunikat o bB�dzie ORA-06503:
PL/SQL: Function returned without value. Dlatego zawsze warto przeprowadza dogB�bne
testy napisanych program�w.
Procedury a funkcje
Uog�lniajc, funkcja sBu|y do przeprowadzenia pewnych operacji, kt�rych celem jest otrzyma-
nie pewnej warto[ci. Oczywi[cie, jest mo|liwe wykorzystanie procedury zamiast funkcji i za-
stosowanie pojedynczego parametru OUT, jednak takie postpowanie nie jest zalecane.
Warto te| pamita, |e nie nale|y pisa program�w, kt�re zwracaj warto[ informujc o stanie
zakoDczenia. Postpowanie takie jest uzasadnione w jzyku takim jak C, lecz w przypadku
PL/SQL informowanie o bBdach powinno si odbywa poprzez przechwytywanie wyjtk�w.
Je[li program magazynowany nie przechwyci wyjtku, zakBada si, |e podczas wykonania tego
programu nie napotkano |adnych problem�w.
Czasami okazuje si, |e istnieje potrzeba zwr�cenia wicej ni| jednej warto[ci w takim przy-
padku nale|y utworzy procedur. W celu zwr�cenia wielu warto[ci trzeba wykorzysta kilka
parametr�w w trybie OUT lub IN OUT, kt�rych warto[ mo|e by odczytana przez program
wywoBujcy po zakoDczeniu dziaBania procedury. Zdefiniowanie kilku parametr�w w trybie
OUT mo|e wprowadzi nieco zamieszania, jednak istnieje metoda zapisywania program�w, kt�-
re musz zwraca wiksz ilo[ danych w bardziej czytelny spos�b. Mo|na bowiem r�|ne ele-
menty poBczy w jedn caBo[ przez zastosowanie jednego ze zBo|onych typ�w danych, jak na
przykBad rekord, kolekcja lub tak zwany typ obiektowy. Zagadnienia te opisano w rozdziale 5.
3. Program wywoBujcy po wywoBaniu funkcji musi w jaki[ spos�b wykorzysta zwr�con warto[,
na przykBad przypisa j pewnej zmiennej. PL/SQL, w przeciwieDstwie do j�zyka C, nie dopuszcza
wywoBania funkcji i zignorowania zwracanej warto[ci.
4. Po wykonaniu instrukcji RETURN w sekcji wykonawczej do programu wywoBujcego zostaje
przekazana nie tylko warto[, ale tak|e sterowanie wykonaniem programu. Innymi sBowy, kod
zapisany po instrukcji RETURN nie jest wykonywany.
Warto r�wnie| zwraca uwag� na stosowan terminologi�. Czasami, gdy kto[ m�wi o procedurach
magazynowanych , naprawd� ma na my[li programy magazynowane, czyli albo procedury, albo
funkcje. Z drugiej jednak strony, mo|e chodzi wBa[nie o procedury, nie za[ funkcje. Je[li og�lny
kontekst rozmowy nie pozwala na rozpoznanie, o kt�r mo|liwo[ chodzi, z pewno[ci pro[ba
o wyja[nienie nie b�dzie objawem dyletanctwa.
Powy|ej przedstawiono nast�pujcy spos�b wywoBania funkcji:
DECLARE
ile INTEGER;
BEGIN
ile := book_copy_qty('1-56592-335-9');
END;
/
WydawaBoby si�, |e powy|szy kod mo|na zapisa w bardziej zwi�zBy spos�b poprzez wywoBanie
funkcji podczas inicjalizacji zmiennej:
DECLARE
ile INTEGER := book_copy_qty('xyz');
BEGIN
Z pozoru wszystko jest w porzdku. Jednak je[li funkcja przechwyci wyjtek, to okazuje si�, |e
|aden kod obsBugi wyjtku w tej sekcji nie zdoBa przechwyci wyjtku, kt�ry ewentualnie mo|e
pojawi si� po takim wywoBaniu funkcji book_copy_qty. A zatem:
DECLARE
ile INTEGER := book_copy_qty('xyz');
BEGIN
...cokolwiek...
EXCEPTION
WHEN OTHERS
THEN
/* NIESPODZIANKA! Wyjtki przechwycone w sekcji deklaracji
|| NIE MOG by obsBu|one w tym miejscu!
*/
...
END;
/
WytBumaczenie powodu takiego zachowania wykracza poza zakres niniejszej ksi|ki. Dlatego nale|y
po prostu zapami�ta, |e nie nale|y dokonywa pr�b inicjalizowania zmiennych za pomoc funkcji.
Z pewno[ci Czytelnik chciaBby kontynuowa rozwijanie tworzonej, przykBadowej aplikacji. Nie
mo|na jednak zapomina o konsekwentnym upewnianiu si�, |e zapisany od nie zawiera bB�d�w. Z tego
te| wzgl�du poni|ej zamieszczono pewnego rodzaju dygresj�.
Z pewno[ci ka|dy zetknB si� ju| z wyra|eniem garbage in, garbage out (GIGO). Jest to wyra|e-
nie do[ cz�sto u|ywane lub sByszane przez telefon podczas rozmowy z obsBug techniczn. Oznacza
ono mniej wi�cej tyle, co wprowadzasz bB�dne dane uzyskujesz bB�dne wyniki .
Unikni�cie problemu GIGO jest spraw do[ problematyczn. Istnieje tendencja do nieuzasadnione-
go optymizmu w kwestii wykorzystywania utworzonych aplikacji. Ch�tniej przyjmuje si� zaBo|enie
tidy in, tidy out (wprowadzasz poprawne dane uzyskujesz poprawne wyniki)3. Nikt nie lubi z g�ry
planowa dziaBaD zapobiegawczych wzgl�dem zastosowania niepoprawnych danych wej[ciowych.
W celu unikni�cia nieprzewidzianych zaBamaD programu trzeba przeprowadzi serie test�w. Prze-
prowadzenie dobrych test�w oznacza generowanie przer�|nych kombinacji danych testowych,
kt�re potencjalnie powinny zawiesi program. Potem nale|y sprawdzi oczekiwany wynik, uru-
chomi program, por�wna z danymi wyj[ciowymi, poprawi program i wreszcie& ponownie
przeprowadzi testy.
Z pewno[ci warto upro[ci ten caBy proces.
Monotonne wykonywanie fragmentu kodu z r�|nymi danymi wej[ciowymi jest dobr okazj do na-
pisania pewnych program�w u|ytkowych. Poni|ej przedstawiono spos�b zautomatyzowania tego
m�czcego procesu za pomoc takich program�w.
DziaBanie pierwszego, sprawdzajcego programu polega na por�wnywaniu dw�ch warto[ci i wy[wie-
tlaniu komunikatu o pomy[lnym lub niepomy[lnym przebiegu tego testu. U podstaw testowania
le|y wBa[nie por�wnywanie warto[ci warto[ci faktycznej ze spodziewan warto[ci wyj[ciow.
Dlatego te| wspomniany program jest bardzo u|yteczny. ZawieraB on tak|e opis poszczeg�lnych
iteracji, tak aby umo|liwi otrzymanie informacji o tym, dla jakich warto[ci wykonanie programu
b�dzie niepomy[lne. Poni|ej znajduje si� kod tej procedury test r�wno[ci (testrownosci):
CREATE OR REPLACE PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN VARCHAR2, actual_value IN VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT(description || ': ');
IF expected_value = actual_value
OR (expected_value IS NULL AND actual_value IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('PASSED');
3
NieprzetBumaczalna gra sB�w: garbage to po angielsku [mieci, bzdury; tidy czysty, schludny przyp. tBum.
ELSE
DBMS_OUTPUT.PUT_LINE('FAILED. Expected ' || expected_value
|| '; got ' || actual_value);
END IF;
END;
/
W powy|szej procedurze por�wnywaniu podlegaj cigi znak�w (VARCHAR2), ale mo|na oczywi-
[cie napisa analogiczne procedury obsBugujce liczby, daty czy te| warto[ci logiczne.
Kolejnym krokiem b�dzie napisanie programu wywoBujcego procedur� add_book na wiele spo-
sob�w tak|e w razie zastosowania nieprawidBowych danych wej[ciowych. Poni|szy program ze
wzgl�du na jego obszerno[ (89 linii kodu) podzielono na fragmenty. Dodatkowo ponumerowano
poszczeg�lne linie w celu uBatwienia odwoBywania si� do nich.
1 DECLARE
2 l_isbn VARCHAR2(13) := '1-56592-335-9';
3 l_title VARCHAR2(200) := 'Oracle PL/SQL Programming';
4 l_summary VARCHAR2(2000) := 'Reference for PL/SQL developers, ' ||
5 'including examples and best practice recommendations.';
6 l_author varchar2(200) := 'Feuerstein, Steven, and Bill Pribyl';
7 l_date_published DATE := TO_DATE('01-WRZ-1997', 'DD-MON-YYYY');
8 l_page_count NUMBER := 987;
9 l_barcode_id VARCHAR2(100) := '100000001';
10
11 CURSOR bookCountCur IS
12 SELECT COUNT(*) FROM books;
13
14 CURSOR copiesCountCur IS
15 SELECT COUNT(*) FROM book_copies;
16
17 CURSOR bookMatchCur IS
18 SELECT COUNT(*) FROM books
19 WHERE isbn = l_isbn AND title = l_title AND summary = l_summary
20 AND author = l_author AND date_published = l_date_published
21 AND page_count = l_page_count;
22
23 CURSOR copiesMatchCur IS
24 SELECT COUNT(*) FROM book_copies
25 WHERE isbn = l_isbn AND barcode_id = l_barcode_id;
26
27 how_many NUMBER;
28 l_sqlcode NUMBER;
Poni|ej znajduje si� kilka wyja[nieD dotyczcych przedstawionego fragmentu kodu.
Linie 2. 9. S to deklaracje zmiennych lokalnych, kt�re reprezentuj warto[ci u|ywane w r�|nych
testach. Przechowywanie tych warto[ci w zmiennych uBatwia programowanie z uwagi na mo|li-
wo[ ich wielokrotnego u|ycia. Przedrostek l_ oznacza, |e s to zmienne lokalne.
Linie 11. 12. Jest to deklaracja pierwszego z kursor�w programu. Kursor umo|liwia pobieranie
warto[ci z bazy danych za pomoc instrukcji j�zyka SQL SELECT. Ta konkretna instrukcja oblicza
caBkowit liczb� rekord�w w tabeli ksiazki.
Linie 14. 15. Jest to r�wnie| deklaracja kursora programu umo|liwia on obliczanie caBkowi-
tej liczby egzemplarzy ksi|ki.
Linie 17. 21. Ten kursor sBu|y do obliczania liczby ksi|ek, dla kt�rych warto[ci kolumn odpo-
wiadaj warto[ciom zmiennych lokalnych.
Linia 27. Zmienna lokalna ile przechowuje tymczasowo rezultat dziaBania powy|szych zapytaD.
Linia 28. Zmienna l_sqlcode przechowuje tymczasowo warto[ wyj[ciow wewn�trznej funk-
cji PL/SQL SQLCODE. Jej dziaBanie zostanie om�wione nieco dalej.
Poni|ej przedstawiono sekcj� wykonawcz omawianego programu. Rozpoczyna ona swoje dziaBa-
nie od usuni�cia zawarto[ci obydw�ch tabel w bazie danych. W ten spos�b uzyskuje si� pewno[,
|e wszelkie operacje zliczania b�d dotyczy jedynie bie|cych danych testowych, a nie innych,
kt�re mogBy pozosta po wcze[niejszych wykonaniach. Oczywi[cie, caBa ta procedura powinna doty-
czy pewnej testowej bazy danych, a nie bazy podstawowej.
29 BEGIN
30 DELETE book_copies;
31 DELETE books;
32
33 add_book(isbn_in => l_isbn, barcode_id_in => l_barcode_id,
34 title_in => l_title, summary_in => l_summary, author_in => l_author,
35 date_published_in => l_date_published, page_count_in =>
l_page_count);
36
37 OPEN bookMatchCur;
38 FETCH bookMatchCur INTO how_many;
39 reporteqbool('add procedure, book fetch matches insert',
40 expected_value => TRUE, actual_value => bookMatchCur%FOUND);
41 CLOSE bookMatchCur;
42
Linie 33. 41. W tym miejscu nast�puje pierwsze wywoBanie procedury add_book. Wykorzy-
stywane s wszystkie zdefiniowane wcze[niej parametry i oczekiwane jest poprawne zakoDczenie
procedury. WywoBanie to rozpoczyna proces sprawdzajcy, czy procedura dodawania ksi|ki
dziaBa poprawnie. Nast�puje to przez otwarcie kursora, pobranie z niego danych i sprawdzenie,
czy, zgodnie z oczekiwaniami, rekord zostaB utworzony. W liniach 39. 40. znajduje si� wywoBa-
nie procedury reporteqbool jest to odmiana procedury reporteq, kt�ra wykorzystuje
warto[ci logiczne (Boolean) zamiast cig�w znak�w. Je[li pobranie danych do kursora koDczy si�
powodzeniem, warto[ci bookMatchCur%FOUND jest TRUE (wi�cej informacji na temat wyko-
rzystania tej techniki znajduje si� w rozdziale 5.). Jak wynika z tre[ci linii 41., dobrym zwyczajem
jest zamykanie kursora po jego u|yciu.
43 BEGIN
44 add_book(isbn_in => NULL, barcode_id_in => 'foo', title_in => 'foo',
45 summary_in => 'foo', author_in => 'foo',
46 date_published_in => SYSDATE, page_count_in => 0);
47 l_sqlcode := SQLCODE;
48 EXCEPTION
49 WHEN OTHERS THEN
50 l_sqlcode := SQLCODE;
51 END;
52
53 reporteq('add procedure, detection of NULL input',
54 expected_value => '-6502', actual_value => TO_CHAR(l_sqlcode));
55
Linie 43. 54. Ten fragment kodu sBu|y do przeprowadzenia kolejnego testu tym razem nast�-
puje pr�ba okre[lenia warto[ci NULL dla parametru isbn w celu sprawdzenia prawidBowego
dziaBania detekcji bB�dnych danych wej[ciowych. Je[li procedura add_book dziaBa poprawnie, po-
winna przechwyci wyjtek NO_DATA_FOUND. Programista powinien zosta poinformowany o tym
fakcie, a zatem tekst zostaB umieszczony w bloku zagnie|d|onym. W ten spos�b mo|na obsBu|y
wyjtek niejako w kolejnej instrukcji zamiast przeskakiwa do koDcowej cz�[ci bloku gB�wnego
(sekcji obsBugi wyjtk�w).
W celu zachowania zgodno[ci z innymi przeprowadzanymi testami, tu r�wnie| trzeba przeprowa-
dzi por�wnanie otrzymanej warto[ci z pewn warto[ci oczekiwan. PL/SQL zawiera specjaln
funkcj� wewn�trzn SQLCODE, kt�ra wywoBana z poziomu kodu obsBugi wyjtku zawsze zwraca
okre[lon warto[ r�|n od zera. Z uwagi na fakt, |e warto[ ta ma zosta wykorzystana poza ko-
dem obsBugi wyjtku, w linii 50. nast�puje przypisanie tej warto[ci zmiennej l_sqlcode, kt�ra
nast�pnie jest wykorzystywana w liniach 53. i 54. podczas wywoBania procedury reporteq.
Z linii 54. wynika, |e warto[ oczekiwana wynosi 6502. Jest to warto[, kt�r PL/SQL przypi-
suje SQLCODE w sytuacji, gdy pojawia si� wyjtek NO_DATA_FOUND.
56 OPEN bookCountCur;
57 FETCH bookCountCur INTO how_many;
58 reporteq('add procedure, book_record count', expected_value => '1',
59 actual_value => how_many);
60 CLOSE bookCountCur;
61
62 OPEN copiesCountCur;
63 FETCH copiesCountCur INTO how_many;
64 reporteq('add procedure, book_copy record count', expected_value => '1',
65 actual_value => how_many);
66 CLOSE copiesCountCur;
67
68 OPEN copiesMatchCur;
69 FETCH copiesMatchCur INTO how_many;
70 reporteqbool('add procedure, book copy fetch matches insert',
71 expected_value => TRUE, actual_value => copiesMatchCur%FOUND);
72 CLOSE copiesMatchCur;
73
Linie 56. 72. Kolejne linie kodu sBu| do sprawdzenia, czy w tabeli znajduje si� oczekiwana liczba
rekord�w.
74 BEGIN
75 add_book(isbn_in => l_isbn, barcode_id_in => l_barcode_id,
76 title_in => l_title, summary_in => l_summary, author_in =>
l_author,
77 date_published_in => l_date_published,
78 page_count_in => l_page_count);
79 l_sqlcode := SQLCODE;
80 EXCEPTION
81 WHEN OTHERS THEN
82 l_sqlcode := SQLCODE;
83 END;
84 reporteq('add procedure, detection of duplicate isbn',
85 expected_value => '-1', actual_value => l_sqlcode);
86 END;
87 /
Linie 74. 85. Kolejny test, uwzgl�dniony w omawianym programie, polega na sprawdzeniu, czy
pr�ba wprowadzenia drugi raz tej samej warto[ci isbn spowoduje przechwycenie wyjtku. Sys-
tem Oracle powinien w takiej sytuacji ustawi warto[ SQLCODE na 1, co oznacza wBa[nie pr�b�
wstawienia rekordu o takim samym kluczu gB�wnym, co rekord ju| istniejcy (w rzeczywisto[ci jest
to test poprawno[ci projektu bazy danych).
Jest to w zasadzie ostatni punkt kontrolny testu poprawno[ci procedury add_book. Je|eli przed
uruchomieniem programu wykonano komend� SERVEROUTPUT ON (dokBadniejszy opis znajduje
si� w rozdziale 2.), wywoBanie omawianego programu z poziomu SQL*Plus powoduje wy[wietle-
nie nast�pujcych informacji:
add procedure, book fetch matches insert: PASSED
add procedure, detection of null input: PASSED
add procedure, book record count: PASSED
add procedure, book_copy record count: PASSED
add procedure, book_copy fetch matches insert: PASSED
add procedure, detection of duplicate isbn: PASSED
By mo|e Czytelnik zauwa|yB, |e powy|szy kod sBu|y jako test jednostki programowej (unit test)4.
Mo|e on tak|e posBu|y jako zapisany przykBad wywoBywania programu, co mo|e okaza si� przy-
datne w razie zaistnienia wtpliwo[ci dotyczcych sposobu przeprowadzenia podobnej procedury.
Poni|szy program sBu|y do testowania pracy funkcji book_copy_qty. Zasadniczo spos�b jego
dziaBania jest taki sam, jak w przypadku poprzedniego programu.
1 DECLARE
2 l_isbn VARCHAR2(13) := '1-56592-335-9';
3 l_isbn2 VARCHAR2(13) := '2-56592-335-9';
4 l_title VARCHAR2(200) := 'Programowanie w Oracle PL/SQL';
5 l_summary VARCHAR2(2000) := 'Kompendium informacji o jzyku PL/SQL ' ||
6 'wraz z przykBadami i poradami na temat programowania.';
7 l_author varchar2(200) := 'Feuerstein, Steven, Bill Pribyl';
8 l_date_published DATE := TO_DATE('01-WRZ-1997', 'DD-MON-YYYY');
9 l_page_count NUMBER := 987;
10 l_barcode_id VARCHAR2(100) := '100000001';
11 l_barcode_id2 VARCHAR2(100) := '100000002';
12 l_barcode_id3 VARCHAR2(100) := '100000003';
13
14 how_many NUMBER;
15 BEGIN
16 DELETE book_copies;
17 DELETE books;
4
Wyra|enie jednostka programowa (unit) odnosi si� tu do pojedynczej jednostki programowej
w przeciwieDstwie do innych rodzaj�w test�w, kt�re pozwalaj upewni si�, co do prawidBowej
wsp�Bpracy poszczeg�lnych jednostek w ramach caBej aplikacji.
18
19 reporteq('book_copy_qty function, zero count', '0',
20 TO_CHAR(book_copy_qty(l_isbn)));
21
22 /* ZakBadamy, |e procedura add_book dziaBa prawidBowo */
23 add_book(isbn_in => l_isbn, barcode_id_in => l_barcode_id,
24 title_in => l_title, summary_in => l_summary, author_in => l_author,
25 date_published_in => l_date_published, page_count_in =>
l_page_count);
26
27 reporteq('book_copy_qty function, unit count', '1',
28 TO_CHAR(book_copy_qty(l_isbn)));
29
30 add_book_copy(isbn_in => l_isbn, barcode_id_in => l_barcode_id2);
31 add_book_copy(isbn_in => l_isbn, barcode_id_in => l_barcode_id3);
32
33 reporteq('book_copy_qty function, multi count', '3',
34 TO_CHAR(book_copy_qty(l_isbn)));
35
36 reporteq('book_copy_qty function, null ISBN', '0',
37 TO_CHAR(book_copy_qty(NULL)));
38 END;
39 /
Linie 30. 31. Ten fragment kodu zawiera wywoBania procedury, kt�ra jeszcze nie zostaBa Czy-
telnikowi przedstawiona. Procedura ta sBu|y do wstawienia rekordu do tabeli book_copies.
Je|eli uruchomienie jednostki testowej powoduje wy[wietlenie wynik�w pokazanych poni|ej (przy
zaBo|eniu, |e przed uruchomieniem programu wykonano polecenie SERVEROUTPUT ON), ozna-
cza to prawidBowe dziaBanie funkcji book_copy_qty:
book_copy_qty function, zero count: PASSED
book_copy_qty function, unit count: PASSED
book_copy_qty function, multi count: PASSED
book_copy_qty function, null ISBN: PASSED
By mo|e Czytelnik si� zastanawia nad zasadno[ci tworzenia takiej ilo[ci dodatkowego kodu. By
mo|e po prostu wystarczyBoby przegldanie programu w celu wyszukania ewentualnych bB�d�w.
Takie sprawdzanie kodu jest sposobem post�powania przeci�tnego programisty. Istot� problemu
najlepiej oddaje sprawdzenie warto[ci NULL, wykonywane w liniach 40. 41. omawianego pro-
gramu sprawdzajcego. Co prawda, ostateczny test wersji procedury add_book przebiegB po-
my[lnie, jednak pocztkowo Autorzy wcale nie brali pod uwag� konieczno[ci sprawdzania warto-
[ci NULL. Dopiero w trakcie pisania jednostki testowej okazaBo si�, |e nale|y uwzgl�dni co najmniej
trzy przypadki wprowadzania danych wej[ciowych: okre[lenie danych poprawnych, niepoprawnych
oraz uwzgl�dnienie tej problematycznej warto[ci NULL. UstaleD tych dokonano jedynie dzi�ki anali-
zie mo|liwych danych wej[ciowych, kt�re nale|y uwzgl�dnia podczas planowania test�w. Wcze-
[niejsze poprawne dziaBanie programu okazaBo si� kwesti przypadku. Testowanie i spos�b jego
zaplanowania umo|liwia analiz� tworzonego kodu z zupeBnie odmiennego punktu widzenia, co po-
zwala na uzyskanie nowych, wa|nych informacji.
Czas przeznaczony na testowanie aplikacji jest niekiedy ograniczany z powod�w finansowych
lub w rezultacie decyzji kierownictwa firmy. Cz�[ciej jednak testowanie aplikacji jest pomijane
przez programist�w, kt�rzy postrzegaj t� czynno[ jako nudn lub nawet niepotrzebn.
Bezwzgl�dnie nale|y jednak wyrobi sobie nawyk testowania pisanych przez siebie aplikacji.
Dotychczas Czytelnik zapoznaB si� z kodem umo|liwiajcym przeprowadzanie kilku operacji zwi-
zanych z obsBug katalogu. Przedstawiono tak|e kod kilku narz�dzi sBu|cych do testowania.
Poni|ej opisano pewne uproszczenia, jakie dotychczas dopuszczano wobec omawianego problemu.
Przedstawiono tak|e kilka sposob�w pokonania tych ograniczeD.
Kod, kt�ry zaprezentowano we wcze[niejszych podrozdziaBach, nie rozwizuje jeszcze pewnych
wa|nych zagadnieD, takich jak:
" Mo|liwo[, |e rekord wstawiany do tabeli books ju| istnieje. Trzeba sprawdzi, czy jest
to traktowane tak samo, jak wprowadzenie informacji o nowym egzemplarzu.
" Spos�b modyfikowania danych w katalogu.
" Sytuacja, w kt�rej dany rekord katalogu biblioteki zostanie przypadkowo usuni�ty lub utracony.
Trzeba przeanalizowa mo|liwo[ci wykorzystania PL/SQL do przekazania tej informacji
do systemu bazy danych.
" Sytuacja, w kt�rej zaistnieje potrzeba wykonania wielu r�|nych zapytaD, np. wyszukiwanie
ksi|ek na podstawie kilku r�|nych kryteri�w.
Oczywi[cie, w dalszej cz�[ci niniejszej ksi|ki zostan przedstawione sposoby rozwizania wielu
z powy|szych problem�w. Zaprezentowane b�d odpowiednie fragmenty kodu i spos�b ich doda-
wania. Z powy|szego wynika, |e wygodnym rozwizaniem byBoby posiadanie mechanizmu pozwa-
lajcego na organizowanie kodu w taki spos�b, aby umo|liwi jego Batwiejsze rozwijanie i utrzy-
mywanie. Mechanizmem takim s pakiety (packages).
Pakiet j�zyka PL/SQL jest pewnym nazwanym zbiorem, kt�ry mo|e zwiera dowoln liczb� pro-
cedur i funkcji. Pakiety mog tak|e przechowywa inne obiekty, na przykBad wyjtki, zmienne czy
deklaracje typ�w danych. W trakcie lektury dalszej cz�[ci niniejszej ksi|ki Czytelnik przekona
si� o ogromnych korzy[ciach, kt�re pByn z tych dodatkowych mo|liwo[ci. W tym rozdziale jednak
zostanie przedstawiony tylko spos�b wykorzystania teoo mechanizmu do wstawienia ju| utworzo-
nego programu do pakietu.
W przypadku innych j�zyk�w programowania na przykBad Java lub Ada tak|e istniej
konstrukcje zwane pakietami. Jednak pakiety w j�zyku PL/SQL charakteryzuj specyficzne
definicje i zachowania. Warto o tym pami�ta w przypadku zapoznawania si� z tymi strukturami
w innych j�zykach.
Z powod�w, kt�re stan si� niedBugo oczywiste, pakiety skBadaj si� zazwyczaj z dw�ch cz�[ci:
specyfikacji (specification) w skr�cie spec oraz ciaBa (body).
Specyfikacja pakietu zawiera jedynie informacje o jego mo|liwo[ciach (przeznaczeniu), ale nie ma
tu |adnych wiadomo[ci o sposobie jego wykonania. Specyfikacja zawiera jedynie nagB�wki jednostek
programowych, a nie kod wykonywalny. Jest to rodzaj sekcji deklaracyjnej, wyst�pujcej w jed-
nostkach programowych. Uproszczony wzorzec skBadni definicji pakietu przedstawiono poni|ej:
CREATE OR REPLACE PACKAGE nazwa_pakietu
AS
nagB�wek_programu1;
nagB�wek_programu2;
nagB�wek_programu3;
END nazwa_pakietu;
/
nazwa_pakietu jest opisow nazw, jak u|ytkownik nadaje danemu pakietowi (nazwa ta podle-
ga zasadom nadawania nazw obowizujcym w j�zyku PL/SQL).
Poni|ej przedstawiono spos�b utworzenia pakietu, sBu|cego do zarzdzania ksi|kami w bazie
danych. Pierwszym problemem jest nadanie odpowiedniej nazwy. Cz�[ programist�w uwa|a, |e
taki rodzaj pakietu peBni rol� zarzdcy (manager) i dlatego zastosowan przez nich nazw byBoby
book_mgr lub book_man. Inni raczej podkre[laj rodzaj obiektu i u|yliby nazwy book_pkt.
Autorzy preferuj jednak nazwy kr�tkie i proste a zatem wybrali prost nazw� book5.
Poni|ej przedstawiono przykBadow specyfikacj� pakietu:
CREATE OR REPLACE PACKAGE book
AS
PROCEDURE add(isbn_in IN VARCHAR2, title_in IN VARCHAR2,
author_in IN VARCHAR2, page_count_in IN NUMBER,
summary_in IN VARCHAR2 DEFAULT NULL,
date_published_in IN DATE DEFAULT NULL,
barcode_id_in IN VARCHAR2 DEFAULT NULL);
PROCEDURE add_copy(isbn_in IN VARCHAR2, barcode_id_in IN VARCHAR2);
FUNCTION book_copy_qty(isbn_in IN VARCHAR2)
RETURN NUMBER;
PROCEDURE change(isbn_in IN VARCHAR2, new_title IN VARCHAR2,
new_author IN VARCHAR2, new_page_count IN NUMBER,
new_summary IN VARCHAR2 DEFAULT NULL,
new_date_published IN DATE DEFAULT NULL);
5
WywoBywanie program�w umieszczonych w pakietach odbywa si� w nast�pujcy spos�b: nazwa_pakietu.
nazwa_programu std mo|liwe okazuje si� u|ywanie zwi�zBych, lecz zrozumiaBych wywoBaD w rodzaju
book.add(...).
PROCEDURE remove_copy(barcode_id_in IN VARCHAR2);
PROCEDURE weed(isbn_in IN VARCHAR2);
END book;
/
W wi�kszo[ci przypadk�w (tak|e w powy|szym) nie ma potrzeby umieszczania w specyfikacji pa-
kietu procedur i funkcji w okre[lonym porzdku.
Warto zauwa|y, |e instrukcja definicji specyfikacji pakietu rozpoczyna si� od wyra|enia CREATE
OR REPLACE, za[ poszczeg�lne programy w nagB�wku maj posta:
FUNCTION nazwa ...
lub:
PROCEDURE nazwa ...
Jest to spowodowane faktem, |e w przypadku j�zyka PL/SQL caBy kod pojedynczego pakietu jest
tworzony, uaktualniamy lub usuwany jednocze[nie, tak wi�c sensowne jest tylko zastosowanie jed-
nej instrukcji CREATE.
Z powy|szego wynika, |e w planach rozwoju aplikacji uwzgl�dniono dodanie kilku brakujcych funk-
cji (jednak|e metody niezb�dne do pobierania danych z bazy danych nie zostan na razie utworzone).
Specyfikacja pakietu peBni rol� interfejsu programowania aplikacji (application programming
interface, API) w odniesieniu do pakietu. Nazwa ta jest by mo|e nieco nie[cisBa, lecz oddaje istot�
idei stosowania pakietu. Ka|dy API sBu|y bowiem jako forma komunikacji mi�dzy u|ytkownikami
(np. mi�dzy piszcymi program i wykorzystujcymi go). Sens takiego post�powania polega na ukry-
ciu niejednokrotnie bardzo skomplikowanych rozwizaD programistycznych za ich prost prezentacj.
CiaBo pakietu zawiera elementy strukturalne jednostek programowych, czyli instrukcje wykonawcze
odpowiadajce nagB�wkom podanym w specyfikacji pakietu. Uproszczony wzorzec skBadniowy
ciaBa pakietu znajduje si� poni|ej:
CREATE OR REPLACE PACKAGE BODY nazwa_pakietu
AS
programy_prywatne; /* opcjonalnie */
ciaBo_programu1;
ciaBo_programu2;
ciaBo_programu3;
END nazwa_pakietu;
/
Innymi sBowy, ciaBo pakietu jest t lokalizacj, gdzie si� umieszcza implementacje program�w wy-
mienionych w specyfikacji.
Niemal zawsze ciaBo pakietu tworzy si� po zdefiniowaniu jego specyfikacji. Kompilator sprawdza,
z kt�r specyfikacj jest zwizane dane ciaBo poprzez sprawdzenie jego nazwy, kt�ra musi by iden-
tyczna z wymienion w specyfikacji. Ponadto ciaBo pakietu musi zawiera definicje wszystkich
program�w, jakie zostaBy wymienione w specyfikacji w przeciwnym wypadku kompilacja si�
nie powiedzie. Jednak|e warto zauwa|y, |e zasada ta nie dziaBa odwrotnie ciaBo pakietu mo|e
zawiera pewne dodatkowe programy, kt�rych nie wymieniono w specyfikacji pakietu. Na przed-
stawionym powy|ej wzorcu opisano je jako programy_prywatne.
Kod ciaBa pakietu book zawiera jedn procedur� prywatn (private):
CREATE OR REPLACE PACKAGE BODY book
AS
/* "prywatna" procedura u|ywana tylko w ciele tego pakietu */
PROCEDURE assert_notnull (tested_variable IN VARCHAR2)
IS
BEGIN
IF tested_variable IS NULL
THEN
RAISE VALUE_ERROR;
END IF;
END assert_notnull;
FUNCTION book_copy_qty(isbn_in IN VARCHAR2)
RETURN NUMBER
AS
number_o_copies NUMBER := 0;
CURSOR bc_cur IS
SELECT COUNT(*)
FROM book_copies
WHERE isbn = isbn_in;
BEGIN
IF isbn_in IS NOT NULL
THEN
OPEN bc_cur;
FETCH bc_cur INTO number_o_copies;
CLOSE bc_cur;
END IF;
RETURN number_o_copies;
END;
PROCEDURE add(isbn_in IN VARCHAR2, title_in IN VARCHAR2,
author_in IN VARCHAR2, page_count_in IN NUMBER,
summary_in IN VARCHAR2, date_published_in IN DATE,
barcode_id_in IN VARCHAR2)
IS
BEGIN
assert_notnull(isbn_in);
INSERT INTO books (isbn, title, summary, author, date_published,
page_count)
VALUES (isbn_in, title_in, summary_in, author_in, date_published_in,
page_count_in);
IF barcode_id_in IS NOT NULL
THEN
add_copy(isbn_in, barcode_id_in);
END IF;
END add;
PROCEDURE add_copy(isbn_in IN VARCHAR2, barcode_id_in IN VARCHAR2)
IS
BEGIN
assert_notnull(isbn_in);
assert_notnull(barcode_id_in);
INSERT INTO book_copies (isbn, barcode_id)
VALUES (isbn_in, barcode_id_in);
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
NULL;
END;
PROCEDURE change(isbn_in IN VARCHAR2, new_title IN VARCHAR2,
new_author IN VARCHAR2, new_page_count IN NUMBER,
new_summary IN VARCHAR2 DEFAULT NULL,
new_date_published IN DATE DEFAULT NULL)
IS
BEGIN
assert_notnull(isbn_in);
UPDATE books
SET title = new_title, author = new_author, page_count =
new_page_count,
summary = new_summary, date_published = new_date_published
WHERE isbn = isbn_in;
IF SQL%ROWCOUNT = 0
THEN
RAISE NO_DATA_FOUND;
END IF;
END change;
PROCEDURE remove_copy(barcode_id_in IN VARCHAR2)
IS
BEGIN
assert_notnull(barcode_id_in);
DELETE book_copies
WHERE barcode_id = barcode_id_in;
END remove_copy;
PROCEDURE weed(isbn_in IN VARCHAR2)
IS
BEGIN
assert_notnull(isbn_in);
DELETE book_copies WHERE isbn = isbn_in;
DELETE books WHERE isbn = isbn_in;
IF SQL%ROWCOUNT = 0
THEN
RAISE NO_DATA_FOUND;
END IF;
END weed;
END book;
/
W powy|szym, do[ dBugim przykBadzie znajduje si� kilka dotd nie om�wionych konstrukcji, przy-
kBadowo, konstrukcja SQL%ROWCOUNT. Zostan one jednak om�wione w dalszych rozdziaBach.
Wi�kszo[ programist�w umieszcza programy w ciele pakietu w takiej samej kolejno[ci, jak w przy-
padku specyfikacji (programy prywatne uwzgl�dnia si� na pocztku, gdy| ze wzgl�du na wymagania
kompilatora ich definicja musi si� znajdowa przed ewentualnym wywoBaniem). W razie niezdefi-
niowania kt�rej[ z jednostek programowych, wymienionych w specyfikacji, kompilator nie prze-
prowadzi kompilacji, dop�ki bBd ten nie zostanie naprawiony.
programy_prywatne s prywatne w sensie dost�pno[ci jedynie z poziomu pakietu. Jego u|yt-
kownicy nie mog bezpo[rednio wywoBywa |adnego z program�w prywatnych. Pozwala to na
konstruowanie narz�dzi o specjalnym przeznaczeniu, kt�re b�d dost�pne tylko dla innych pro-
gram�w, zdefiniowanych w ramach pakietu. W podanym wy|ej przykBadzie dodano tylko jedn,
prost procedur� assert_notnull, kt�ra pozwala na niepowtarzanie kilku linii kodu w ka|dej
definiowanej procedurze. U|ywanie takich lokalnych program�w cz�sto jest bardzo wygodne.
Najcz�[ciej speBniaj one nast�pujce zadania:
" sBu| jako dodatkowe metody, wykorzystywane przez inne programy zawarte w pakiecie;
" pozwalaj na unikni�cie powtarzania tego samego kodu;
" s dobr metod przechowywania lub zmieniania warto[ci pewnej zmiennej wewn�trznej.
Z kolei programy, kt�re s wymienione w specyfikacji pakietu, mog by wywoBywane w dowol-
ny spos�b i nazywa si� je programami publicznymi (public). Rysunek 3.7 przedstawia graficzn
reprezentacj� por�wnania program�w publicznych z prywatnymi.
Rysunek 3.7. Pakiety udostpniaj interfejs publiczny ukrywajcy wewntrzn implementacj
Wielu programist�w nie dostrzega wa|no[ci zagadnieD zwizanych z wykorzystaniem program�w
publicznych i prywatnych, mimo |e jest to jedna z technik pozwalajcych na tworzenie trwaBego,
zrozumiaBego i Batwego do ponownego wykorzystania kodu. Informatycy, kt�rzy wszystkiemu na-
daj pewne formalne nazwy, powiedzieliby, |e oznacza to tworzenie abstrakcji (abstraction) ksi|ki
poprzez ukrywanie informacji (information hiding) patrz: sBowniczek.
Poni|ej wymieniono najistotniejsze korzy[ci wynikajce z wykorzystywania pakiet�w:
Organizacja
Wi�kszo[ ludzi docenia dobre zorganizowanie dziaBania. Grupowanie powizanych ze sob
jednostek programowych w pakiety pozwala na tworzenie kodu zorganizowanego w wygodne
do stosowania struktury. U|ywajc terminologii fachowej mo|na powiedzie, |e pakiety pozwalaj
na u|ycie mechanizm�w abstrakcji, enkapsulacji oraz ukrywania informacji.
ZrozumiaBo[
Pakiety w ogromnym stopniu uBatwiaj zarzdzanie du| liczb jednostek programowych.
Pewne badania z dziedziny psychologii dowiodBy, |e czBowiek w jednym czasie mo|e zajmowa
si� jedynie okoBo siedmioma zagadnieniami. Oczywi[cie, nie zawsze mo|na ograniczy liczb�
komponent�w pakietu do takiej liczby, ale ich grupowanie z pewno[ci uBatwia prac�.
Mo|liwo[ci projektowe
Rozwizanie skomplikowanego problemu odbywa si� zazwyczaj na drodze rozbicia go
na mniejsze skBadowe. Dwa najpopularniejsze, zupeBnie od siebie r�|ne, sposoby rozwizywania
tego problemu (czyli dekompozycji) to podej[cie funkcjonalne (functional) oraz obiektowe
(object-based). Zastosowanie pakiet�w wspomaga obydwie te techniki projektowe.
Wydajno[
Podczas pierwszego w danej sesji uruchomienia programu zapisanego w pakiecie system Oracle
wczytuje do pami�ci caB zawarto[ pakietu, a nie tylko program wBa[nie wywoBany. Pozwala
to na znaczce zwi�kszenie wydajno[ci wywoBania innych program�w pakietu, gdy| nie b�dzie
konieczne korzystanie z danych zapisanych na wolniejszym dysku twardym. Z powy|szego
jednocze[nie wynika, |e w pakiecie warto przechowywa tylko te komponenty, kt�re s
ze sob zwizane.
Wygoda pracy sesyjnej
Czasem jest przydatna mo|liwo[ przechowywania w pami�ci pewnych tymczasowych lub
staBych warto[ci w trakcie trwania sesji (przyj�to, |e sesj nazywa si� okres zalogowania
u|ytkownika w systemie bazy danych). Dzi�ki wykorzystaniu pakiet�w warto[ci takie mo|na
przechowywa w globalnych lub lokalnych zmiennych. Trzeba jednak pami�ta, |e cecha ta
staje du|o mniej przydatna w przypadku aplikacji dziaBajcych w sieci Internet. Aplikacje te
zazwyczaj nie s zale|ne od sesji wi�cej informacji dotyczcych tego tematu znajduje si�
w rozdziale 4. Bez zastosowania pakiet�w warto[ci takie musiaByby by przechowywane
w samej bazie danych, co miaBoby niekorzystny wpByw na wydajno[ systemu. Problematyczne
te| staBoby si� odwoBywanie si� do pewnej warto[ci po wycofaniu transakcji.
Szczeg�lne cechy PL/SQL
Jedn z najciekawszych mo|liwo[ci uzyskiwanych dzi�ki wykorzystaniu pakiet�w jest
mo|liwo[ tworzenia wielu jednostek programowych o takiej samej nazwie. Pozwala to
na wywoBywanie jednego programu, kt�ry mo|e obsBugiwa dane wej[ciowe o r�|nych typach.
Zastosowanie tej techniki, zwanej przeci|aniem (overloading) i niedost�pnej dla program�w
napisanych bez u|ycia pakiet�w, pozwala na uczynienie programu pozornie bardziej og�lnym.
PrzykBadowo, funkcja TO_CHAR systemu Oracle jest przeci|ana w celu umo|liwienia
przyjmowania parametr�w o r�|nym typie danych, na przykBad NUMBER lub DATE. Opis
techniki przeci|ania oraz przykBadowy program znajduj si� w koDcowej cz�[ci niniejszego
rozdziaBu, w podrozdziale Uproszczenie poprzez przeci|enie .
Mniejsze problemy z rekompilacj
W du|ych systemach skBadajcych si� z dziesitk�w lub setek program�w du|ym problemem
jest zazwyczaj rekompilowanie cz�[ci skBadowych programu po dokonaniu pewnych zmian.
Dzi�ki pakietom mo|na unikn wielu trudno[ci dzi�ki temu, |e mo|na rekompilowa zawarto[
ciaBa pakietu bez konieczno[ci rekompilacji program�w, kt�re wykorzystuj zmodyfikowany
program. W przypadku zmiany specyfikacji pakietu trzeba ju| jednak ponownie skompilowa
ka|dy program uwzgl�dniony w pakiecie, ale cz�sto system Oracle robi to automatycznie.
Usuwanie program�w magazynowanych
Warto zwr�ci uwag, |e kod procedury add_book wprowadzony do pakietu nie r�|ni si
od procedury oryginalnej poza zmienion nazw dodaj, gdy| bdzie ona stosowana tylko
w kontek[cie pakietu book.
Oryginalna procedura add_book wci| istnieje, ale mo|na j usun po cz[ci dlatego,
|e dziki wykorzystaniu pakietu procedura ta ju| nie jest potrzebna. Poni|ej zatem pokazano
spos�b usuwania procedury. Odpowiedni instrukcj SQL, kt�ra w nieodwracalny spos�b
usuwa procedur z bazy danych, jest instrukcja DROP PROCEDURE:
DROP PROCEDURE add_book;
Jest to instrukcja SQL, a nie PL/SQL. Std poni|szy spos�b wykonania:
BEGIN
DROP PROCEDURE add_book; /* nie zadziaBa w TYM miejscu */
END;
spowoduje bBd kompilacji i wy[wietlenie komunikatu:
drop procedure add_book;
*
BAD w linii 2:
ORA-06550: linia 2, kolumna 1:
PLS-00103: Napotkano symbol "DROP" gdy oczekiwano jednego z nastpujcych:
...ciach...
Z powy|szego wynika, |e PL/SQL rzeczywi[cie nie jest peBnym nadzbiorem jzyka SQL.
Po usuniciu procedury nie jest mo|liwe jej odzyskanie bez pomocy administratora bazy da-
nych, kt�ry musi przeprowadzi pewne dziaBania zwizane z odzyskiwaniem danych. Je[li
jednak istnieje plik zawierajcy kod zr�dBowy, mo|na po prostu utworzy ponownie dan
procedur.
W rzeczywisto[ci nie powinno si usuwa obiekt�w bazy danych bez upewnienia si, |e nie s
ju| potrzebne w przeciwnym wypadku wcze[niej czy p�zniej spowoduje to problemy.
Dobrym zwyczajem jest przechowywanie specyfikacji oraz ciaBa pakietu w dw�ch oddzielnych
plikach. W ten spos�b Batwo mo|na podda rekompilacji samo ciaBo po dokonaniu pewnych
zmian. Niepotrzebne wykonanie instrukcji zawartych w specyfikacji pakietu sprawiBoby, |e
nieaktualne staByby si� powizania innych program�w z pakietem, a zatem tak|e wymagana
ich rekompilacja.
Jak si� okazuje, istnieje wiele powod�w, dla kt�rych warto u|ywa pakiet�w. A zatem warto powr�-
ci do zagadnieD zwizanych z programami testujcymi i umie[ci je w pakiecie.
Poni|ej przedstawiono spos�b utworzenia kolejnego pakietu. Zorganizowanie procedur testowych
w jednym pakiecie sBu|y ma gB�wnie w celu utrzymania porzdku w kodzie. Na tym etapie zostan
pomini�te kwestie zwizane z wydajno[ci i kilkoma innymi zagadnieniami, kt�re om�wiono wcze-
[niej. Pakiet testujcy zapewnia wygodny spos�b obsBugi, a jego struktura umo|liwia [wietn wsp�B-
prac� ze struktur pakietu book, kt�rego budow� przedstawiono we wcze[niejszej cz�[ci niniejszego
rozdziaBu.
Poni|ej zamieszczono specyfikacj� omawianego pakietu:
CREATE OR REPLACE PACKAGE test_book AS
PROCEDURE run (verbose IN BOOLEAN DEFAULT TRUE);
PROCEDURE add;
PROCEDURE add_copy;
PROCEDURE book_copy_qty;
PROCEDURE change;
PROCEDURE remove_copy;
PROCEDURE weed;
END test_book;
/
Ka|da jednostka programowa gB�wnego pakietu book posiada odpowiednik w pakiecie test_book,
cho nie uwzgl�dniono |adnych parametr�w. Mo|na wywoBywa je pojedynczo lub wywoBa og�ln
procedur� run, kt�ra uruchamia wszystkie pozostaBe. Posiada ona jeden opcjonalny parametr lo-
giczny wskazujcy, czy maj by prezentowane szczeg�Bowe informacje dotyczce test�w. Opr�cz
tego ka|da procedura zawiera kod sBu|cy do testowania.
Je[li wszystko przebiega prawidBowo, przeprowadzenie testu z poziomu SQL*Plus wyglda na-
st�pujco:
SQL> SET SERVEROUTPUT ON SIZE 1000000
SQL> execute test_book.run
Testing book package...
...add procedure, detection of NULL input: PASSED
...add procedure, book_record count: PASSED
...add procedure, book_copy record count: PASSED
...add procedure, book fetch matches insert: PASSED
...add procedure, book copy fetch matches insert: PASSED
...add procedure, detection of duplicate isbn: PASSED
...add_copy procedure, nominal case, first book: PASSED
...add_copy procedure, nominal case, second book: PASSED
...add_copy procedure, ignore duplicates: PASSED
...add_copy procedure, bad isbn detection: PASSED
...add_copy procedure, NULL isbn detection: PASSED
...add_copy procedure, NULL barcode_id detection: PASSED
...book_copy_qty function, zero count: PASSED
...book_copy_qty function, non-zero count: PASSED
...change procedure, single field test: PASSED
...change procedure, NULL barcode_id detection: PASSED
...remove_copy procedure, book count normal: PASSED
...remove_copy procedure, book copy count normal: PASSED
...remove_copy procedure, superfluous invocation: PASSED
...weed procedure, book count normal: PASSED
...weed procedure, book copy count normal: PASSED
...weed procedure, superfluous invocation: PASSED
book package: PASSED
Mo|na tak|e wyBczy tryb szczeg�Bowych komunikat�w, podajc warto[ FALSE przy wywoBa-
niu procedury run. Odpowiednie polecenie przedstawiono poni|ej:
SQL> SET SERVEROUTPUT ON SIZE 1000000
SQL> execute test_book.run(verbose => FALSE)
book package: PASSED
Omawiany pakiet jest zbyt obszerny, aby zamie[ci go w tym miejscu. Posiada on kilka udogodnieD
w por�wnaniu do wersji pierwotnej. PeBna wersja omawianego pakietu znajduje si� pod adresem
ftp://ftp.helion.pl/przyklady/orplsq.zip Odwiedzajc witryn� wydawnictwa O Reilly, Czytelnik mo|e
tak|e zapozna si� z utPLSQL (http://oracle.oreilly.com/utplsql), darmow aplikacj sBu|c do te-
stowania.
By mo|e Czytelnik uwa|a, |e w tre[ci niniejszego rozdziaBu poBo|ono zbyt du|y nacisk na kwesti�
testowania oprogramowania. Warto jednak u[wiadomi sobie, |e programowanie jest dziaBaniem
ukierunkowanym na szczeg�By u|ytkownicy aplikacji s bardzo wymagajcy i jakiekolwiek
lekcewa|enie potencjalnych problem�w jest bardzo ryzykown postaw (istnieje tak zwany styl
programowania ekstremalnego 6 gloryfikujcy tak postaw�). A zatem program testowy nale|y two-
rzy bardzo wcze[nie. Niekt�rzy uwa|aj, |e program testowy powinien by tworzony jeszcze przed
napisaniem gB�wnej aplikacji. Zbyt dBugie zwlekanie z napisaniem programu testowego mo|e w efek-
cie spowodowa, |e nigdy nie powstanie, a nawet je[li powstanie, ewentualna zwBoka mo|e unie-
mo|liwi osigni�cie pewnych korzy[ci wynikajcych z testowania. My[lc o spodziewanych wy-
nikach na wczesnym etapie tworzenia aplikacji Batwiej jest znalez bB�dy i naprawi je szybko i bez
ponoszenia zb�dnych koszt�w.
Pisanie dobrych program�w testowych nie jest zadaniem trywialnym. Dlatego wielu programist�w,
piszcych aplikacje pod presj czasu, stwierdza, |e mo|e pomin ten etap. Warto jednak zapa-
mi�ta nast�pujc dewiz�:
Je[li nie ma czasu, aby wykona zadanie prawidBowo za pierwszym razem, to skd wzi czas,
aby wykona je od nowa?
Autorzy uwa|aj, |e aby zosta naprawd� dobrym programist, nale|y tworzy programy testowe.
Taki spos�b post�powania umo|liwi sp�dzanie wi�kszej ilo[ci czasu na pisaniu nowych program�w,
a mniej na usuwaniu bB�d�w w programach starych.
Po zdobyciu pewnego do[wiadczenia w wykorzystywaniu procedur, funkcji i pakiet�w Czytelnik
z pewno[ci zechce podnie[ poziom swojej pracy programistycznej. Poni|ej znajduje si� kilka po-
rad i sugestii dotyczcych tego zagadnienia.
6
Wi�cej informacji na ten temat mo|na znalez w ksi|ce po[wi�conej tej tematyce, kt�rej autorem jest Kent
Beck lub zajrze na witryn� http://www.extremeprogramming.org/.
Przyj�cie odpowiedniego sposobu nazywania plik�w, kt�re zawieraj kod zr�dBowy tworzonych
program�w, jest z pewno[ci bardzo wa|nym zagadnieniem. PrzykBadowo, w przypadku plik�w
zawierajcych kod PL/SQL warto, aby rozszerzenie nazwy pliku odzwierciedlaBo jego zawarto[.
W rozdziale 6. znajduje si� bardziej szczeg�Bowe om�wienie tego zagadnienia. Poni|ej podano jedy-
nie kilka gB�wnych wytycznych:
Wzorzec nazwy pliku Zawarto[
nazwa.pro
(Pojedyncza) procedura magazynowana
nazwa.fun
(Pojedyncza) funkcja magazynowana
nazwa.sql
Blok anonimowy lub skrypt zawierajcy wiele blok�w, instrukcji SQL i (lub)
poleceD SQL*Plus
nazwa.pks
Specyfikacja pakietu
nazwa.pkb
CiaBo pakietu
W razie zastosowania powy|szych konwencji niekt�re z plik�w, kt�re wymieniono w niniejszym
rozdziale, nosiByby nast�pujce nazwy:
add_book.pro Procedura magazynowana add_book
book_copy_qty.fun Funkcja magazynowana book_copy_qty
test_add_book.sql Program testujcy dla add_book
book.pks Specyfikacja pakietu book
book.pkb CiaBo pakietu book
Specyfikacja i ciaBo pakietu powinny by umieszczone w oddzielnych plikach.
Czytelnik nie powinien sdzi, |e wydajno[ pracy programisty jest wprost proporcjonalna do liczby
linii napisanego kodu. Dawno temu byB to pogld licznych teoretyk�w programowania. Jednak maBe
jest pi�kne programista powinien stara si� osiga du|y efekt kosztem maBego wysiBku. Oto pew-
na historyjka:
Pewien Prawdziwy Programista zdoBaB zmie[ci program dopasowywania do wzorca (pattern
matching) w kilkuset kilobajtach nieu|ywanej pamici sondy Voyager, kt�rej zadaniem byBo
odszukanie i sfotografowanie nowego ksi|yca Jowisza7.
Bez wzgl�du na to, czy powy|sza anegdota jest prawdziwa czy nie, ka|dy programista powinien
stara si� pisa kod zwi�zBy (ale nie niezrozumiaBy). Jednym ze sposob�w na osigni�cie tego celu
jest projektowanie kodu mo|liwego do ponownego wykorzystania. Poni|szy przykBad umo|liwi
zrozumienie problemu.
7
Fragment pochodzi z artykuBu Real Programmers Don t Use PASCAL , Datamation, July 1983, s. 263 265.
Poni|ej przedstawiono dziaBanie procedury reporteq.
Wypisz opis testu.
Por�wnaj warto[ oczekiwan z warto[ci otrzyman.
Je[li obydwie warto[ci s r�wne, wypisz komunikat PASSED, je[li nie FAILED.
Poni|szy kod ju| byB omawiany w niniejszym rozdziale, ale zostaB powt�rzony dla zachowania przej-
rzysto[ci wykBadu.
CREATE OR REPLACE PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN VARCHAR2, actual_value IN VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT(description || ': ');
IF expected_value = actual_value
OR (expected_value IS NULL AND actual_value IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('PASSED');
ELSE
DBMS_OUTPUT.PUT_LINE('FAILED. Expected ' || expected_value
|| '; got ' || actual_value);
END IF;
END;
/
Program ten por�wnuje dwie zmienne typu VARCHAR2. Nast�pna funkcja, reporteqbool, po-
siada identyczny pseudokod, ale jest przeznaczona do por�wnywania warto[ci logicznych typu
BOOLEAN. Mo|na by dokona tylko drobnych modyfikacji w oryginale, jak pokazano w poni|szym
fragmencie kodu:
CREATE OR REPLACE PROCEDURE reporteqbool (description IN VARCHAR2,
expected_value IN BOOLEAN, actual_value IN BOOLEAN) AS
BEGIN
DBMS_OUTPUT.PUT(description || ': ');
IF (expected_value AND actual_value)
OR (expected_value IS NULL AND actual_value IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('PASSED');
ELSE
DBMS_OUTPUT.PUT_LINE('FAILED.');
END IF;
END;
/
Nawet programista, kt�ry nie jest odpowiedzialny za oprogramowanie sondy Voyager, mo|e za-
uwa|y, |e powy|szy kod charakteryzuje si� pewn nadmiarowo[ci. W razie konieczno[ci mody-
fikacji dziaBania cz�[ci testujcej lub raportujcej (na przykBad w celu zapisania wszystkich opis�w
i wynik�w testu w tabeli bazy danych) okazaBoby si�, |e trzeba wykona dwa razy wi�cej pracy.
Problematyczne te| mo|e okaza si� okre[lenie dw�ch r�|nych miejsc, w kt�rych nale|y dokona
zmian. Cz�sto takie zmiany s dokonywane przez kogo[ innego, ni| tw�rca oryginalnej wersji. Oso-
ba taka mo|e nie by [wiadoma istnienia konieczno[ci zmodyfikowania kodu w dw�ch miejscach.
W rezultacie powstanie niezgodno[, kt�rej wykrycie b�dzie kwesti przypadku.
W j�zyku PL/SQL istnieje mo|liwo[ unikni�cia takiego problemu przez zmodyfikowanie drugiej
procedury w taki spos�b, aby wywoBywaBa pierwsz. Aby to umo|liwi, nale|y przekonwertowa
warto[ci logiczne BOOLEAN na VARCHAR2. Niestety, funkcja TO_CHAR nie obsBuguje zmiennych
typu BOOLEAN. Mo|na jednak napisa wBasn funkcj� dokonujc tej konwersji. Zgodnie z obo-
wizujcymi w systemie Oracle zasadami nadawania nazw funkcjom konwersji, jej nazw b�dzie
booleantochar:
CREATE OR REPLACE FUNCTION booleantochar(is_true IN BOOLEAN)
RETURN VARCHAR2
AS
BEGIN
IF is_true
THEN
RETURN 'TRUE';
ELSIF NOT is_true
THEN
RETURN 'FALSE';
ELSE
RETURN TO_CHAR(NULL);
END IF;
END booleantochar;
/
Teraz mo|na ju| zmodyfikowa procedur� reporteqbool w nast�pujcy spos�b:
CREATE OR REPLACE PROCEDURE reporteqbool (description IN VARCHAR2,
expected_value IN BOOLEAN, actual_value IN BOOLEAN)
AS
BEGIN
reporteq(description, booleantochar(expected_value),
booleantochar(actual_value));
END reporteqbool;
/
Najwa|niejsza kwesti, na kt�r nale|y zwr�ci uwag�, jest to, |e caBy kod zwizany z testowa-
niem znajduje si� w procedurze reporteq. A zatem w razie konieczno[ci zmiany sposobu jej
dziaBania wystarczy tylko zmieni kod jednego programu. Nawet je[li osoba zajmujca si� kon-
serwacj danego kodu nie b�dzie wiedziaBa, kt�ry program nale|y zmieni, omawiany spos�b two-
rzenia kodu umo|liwi jej szybkie zorientowanie si� w sytuacji.
Nie jest to jednak ostatnia metoda uBatwiania sobie pracy. Mo|na upro[ci j jeszcze bardziej za
pomoc techniki zwanej przeci|aniem (overloading).
Czytelnik zapewne przypomina sobie, |e we wcze[niejszej cz�[ci niniejszego rozdziaBu opisano
w skr�cie technik� przeci|ania. Opisano utworzenie procedury reporteq, kt�ra obsBuguje cigi
znakowe oraz procedury reporteqbool, wykonujcej por�wnania na warto[ciach logicznych
typu BOOLEAN. Prawdopodobnie potrzebna byBaby tak|e wersja obsBugujca daty funkcja
reporteqdate, i tak dalej. Zadania wykonywane przez te wszystkie programy byByby bardzo
podobne. Warto zatem byBoby utworzy jeden program (lub przynajmniej zastosowa tylko jedn
nazw� programu), kt�ry peBniBby funkcje wszystkich wy|ej wymienionych. PozwoliBoby to na prze-
niesienie wielu obowizk�w u|ytkownika na program u|ytkowy. Im mniej nazw program�w trze-
ba zapami�ta, tym lepiej.
Technika przeci|ania sBu|y wBa[nie do osigni�cia tych cel�w. Uog�lniajc, przeci|enie proce-
dury oznacza zdefiniowanie wi�cej ni| jednej procedury o tej samej nazwie. W ramach pakietu ma
si� w�wczas dost�p do faktycznie czterech r�|nych procedur. Poni|ej znajduje si� przykBad wy-
korzystania tej techniki w pakiecie zawierajcym zbi�r program�w testowych. Poni|ej przedsta-
wiono kod przykBadowej specyfikacji pakietu:
CREATE OR REPLACE PACKAGE tut AS
PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN VARCHAR2, actual_value IN VARCHAR2);
PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN NUMBER, actual_value IN NUMBER);
PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN BOOLEAN, actual_value IN BOOLEAN);
PROCEDURE reporteq (description IN VARCHAR2,
expected_value IN DATE, actual_value IN DATE);
PROCEDURE inna_procedura;
END;
/
Poszczeg�lne procedury reporteq maj t sam nazw� i r�|ni si� tylko typami danych parame-
tr�w. To jest cz�[ ukryta . Nale|y jeszcze zaimplementowa wszystkie cztery procedury w jed-
nym ciele pakietu. Mo|na uwzgl�dni ich wzajemne wywoBywanie si�, co opisano we wcze[niej-
szej cz�[ci niniejszego rozdziaBu. Autorzy pozostawili utworzenie ciaBa pakietu jako wiczenie dla
Czytelnika.
Ogromn zalet techniki przeci|ania jest to, |e u|ywajc takiej procedury lub funkcji PL/SQL,
samodzielnie rozpoznaje ona, kt�r z nich nale|y wywoBa:
DECLARE
rozmiar_buta NUMBER;
rezultat_szukania VARCHAR(64);
BEGIN
...
tut.reporteq('procedura flubber, wykrycie maksymalnego rozmiaru buta',
expected_result => 15, actual_result => rozmiar_buta);
tut.reporteq('procedura flubber, wyszukiwanie morsa',
expected_result => 'Jestem morsem', actual_result => rezultat_szukania);
END;
Oznacza to, |e ka|de wywoBanie procedury reporteq zostaje dopasowane do odpowiedniej sytuacji.
Istnieje kilka sytuacji, w kt�rych metoda przeci|ania nie umo|liwia prawidBowego dziaBania syste-
mu. BBd jednak zostanie zwr�cony dopiero w czasie pr�by uruchomienia programu. Poni|ej wy-
mieniono podstawowe zasady, kt�rych przestrzeganie pozwoli na prawidBowe dziaBanie mechani-
zmu przeci|ania:
1. Przeci|ane programy musz posiada tak sam nazw� oraz znajdowa si� w tym samym
pakiecie8.
8
Mo|na tak|e przeci|a programy doBczone w sekcji deklaracji.
2. Przeci|ane programy musz r�|ni si� albo liczb parametr�w, albo rodzajem typu danych
parametr�w (uwzgl�dniajc pozycyjne por�wnanie). PrzykBadowo, w przypadku mechanizmu
przeci|ania system bazy danych, kt�ry wykonuje program, nie mo|e stwierdzi r�|nicy
pomi�dzy typami NUMBER a INTEGER, ale b�dzie to mo|liwe w przypadku typ�w NUMBER
i VARCHAR2, gdy| nale| one do r�|nych rodzaj�w typ�w danych.
3. Procedura mo|e by przeci|ona funkcj, nawet je[li powy|sze dwa warunki nie s speBnione.
4. Przeci|ane funkcje musz si� r�|ni czym[ wi�cej, ni| tylko typem danych warto[ci zwracanej.
W przypadku niespeBnienia kt�rego[ z wymienionych warunk�w zazwyczaj pojawia si� bBd wy-
konania: PLS-00307: too many declarations of <�nazwa podprogramu> match this call.
W niniejszym rozdziale przedstawiono r�|ne porady dotyczce programowania obronnego. Ten styl
pracy uwzgl�dnia mo|liwo[ wyst�powania najgorszych sytuacji. PrawidBowo napisany program
powinien radzi sobie z bB�dnymi danymi wej[ciowymi nie dajc jednocze[nie bB�dnych danych
wyj[ciowych.
Istnieje co najmniej kilka mo|liwo[ci unikni�cia syndromu bB�d�w na wyj[ciu . Niekt�re z nich
zostaBy om�wione w trakcie omawiania sposobu tworzenia pakietu, kt�ry obsBuguje i chroni dane
o ksi|kach przechowywane w bazie danych. Podsumowujc:
" Nale|y zawsze pami�ta o tym, |e zmienne lub parametry PL/SQL mog mie warto[ NULL,
co jest szczeg�lnie wa|ne w przypadku konstruowania instrukcji IF-THEN.
" Nale|y wykorzystywa obwoluty tabel i rozwija w sobie dyscyplin� potrzebn do u|ywania
tej techniki.
" Podczas deklarowania parametr�w program�w magazynowanych nale|y nadawa warto[ci
domy[lne wsz�dzie tam, gdzie jest to uzasadnione.
" Og�lnie rzecz biorc, nale|y korzysta raczej z notacji wymieniajcej ni| pozycyjnej, szczeg�lnie
w sytuacji, gdy daje to dodatkowe informacje, kt�re nale|y uwzgl�dni.
" Nale|y unika powtarzania tego samego kodu, w przeciwnym razie przyszBe jego modyfikacje
b�d bardziej nara|one na powstawanie bB�d�w.
" Nale|y organizowa kod w postaci pakiet�w, zamiast u|ywania wielu pojedynczych procedur
i funkcji.
" Nale|y obsBugiwa wyjtki tam, gdzie jest to uzasadnione oraz przechwytywa je w sytuacji,
gdy istnieje mo|liwo[ zaistnienia problem�w, kt�rych tworzony program nie b�dzie
rozwizywaB samodzielnie.
" Nale|y korzysta z mechanizmu przeci|ania w celu zmniejszenia zBo|ono[ci aplikacji,
upraszczajc tym samym przyszBy jej rozw�j.
" Nale|y tworzy pewne programy testujce dla ka|dej z tworzonych jednostek programowych.
W kolejnym rozdziale zostanie opisane rozszerzenie tworzonej aplikacji na zewntrz , w kierun-
ku u|ytkownika koDcowego poprzez utworzenie interfejsu u|ytkownika, sBu|cego do obsBugi nie-
kt�rych z cech.
Wyszukiwarka
Podobne podstrony:
Oracle?tabaseg Programowanie w jezyku PL SQL or10ps17 Procedury składowane w języku PL SQL (Oracle)informatyka programowanie serwera oracle 11g sql iOracle?tabaseg Programowanie w jezyku PL SQL or11psOracle8 Programowanie w jezyku PL SQL or8plsSQL10G pl sqlkurs oracle podstawy sqlLinux Tablice informatyczneinformatyka windows 7 pl pierwsza pomoc adam jozefiok ebookzasady sc i zasady etyki ksc tablica informacyjnawięcej podobnych podstron