Rozdział 20
Reguły logiki aplikacji na serwerze
bazy danych
Reguły logiki aplikacji są ograniczeniami, warunkami lub testami, które opisują
zasady realizowania celu organizacji. Mogą one być wyrażone w słowach języka
naturalnego, które techniczni laicy, zaznajomieni ze związanymi z nimi procesami
wykonawczymi, bez trudu zrozumieją. Natomiast fachowcy od baz danych biorą
owe reguły słowne i kodyfikują je w swych bazach danych i aplikacjach. A oto
przykłady niektórych powszechnie spotykanych reguł:
Wszyscy najemcy muszą dostarczyć pełnej informacji o swym zatrudnieniu.
Wszystkie czynsze za najem ustalone są domyślnie na 950$ miesięcznie.
Depozyt zastawny na nieruchomość musi wynosić przynajmniej połowę
wartości czynszu dla tejże nieruchomości.
Czynsz staje się zaległy po upływie pięciu dni od zawartego w umowie najmu
terminu płatności.
Za każdy dzień zwłoki w uiszczeniu czynszu wymierzana jest opłata karna
w wysokości 5$.
Najemcy, dzierżawiący więcej niż jedną nieruchomość, uzyskują 10% zniżki na
każdą dodatkową nieruchomość.
Wszystkie umowy najmu muszą obowiązywać przez przynajmniej sześć
miesięcy.
Nowy najemca nie może wprowadzić się do nieruchomości, zanim nie
rozpocznie się ustalony w umowie okres najmu.
Każda z tych reguł ma w bazie danych lub aplikacji odpowiadający jej element.
Ich artykulacja w
zdaniach języka naturalnego jest zrozumiała dla osób
związanych z danym przedsięwzięciem. Natomiast ich reprezentacja jako zbiór
elementów bazy danych lub aplikacji jest zrozumiała dla programistów baz danych
lub aplikacji. Zdolny „architekt” systemów klient/server będzie w stanie zrozumieć
reguły wypowiedziane na oba sposoby.
W rozdziale tym omawiamy serwerową stronę implementowania reguł logiki
aplikacji w aplikacjach bazodanowych. Są i tacy, którzy implementacje reguł
logiki aplikacji omawiają jako koncepcję teoretyczną, niezależną od ograniczeń
610
Część IV
bazy danych i obiektów programu, niezbędnych do ich zaimplementowania. Ja zaś,
choć zgadzam się w pełni, że zanim przystąpi się do implementowania reguł logiki
aplikacji, trzeba je w pełni zrozumieć, to oddzielanie ich od ich praktycznego
zastosowania uważam za nieporozumienie. Zwłaszcza dlatego, że w końcu i tak
zostaną sprowadzone do realnych obiektów w bazach danych lub programach.
Całkowite oddzielanie reguł logiki aplikacji od ograniczeń, niezbędnych do ich
zaimplementowania, wydaje się nierozsądne także i ze względu na ścisłe
pokrewieństwo między nimi. Fundamentalnym celem każdej organizacji winno
być zapewnienie integralności, lub inaczej spójności, jej danych. Na pewno żadna
firma nie pragnie bazy danych usianej osieroconymi wierszami, niepoprawnymi
wartościami kolumn lub innymi anomaliami w danych. I na odwrót, elementarna
integralność i „spolegliwość” danych jest fundamentem, na którym organizacja
może się oprzeć z pełnym zaufaniem. Tak więc oba te tematy - reguły logiki
aplikacji i integralność danych - są nierozłącznie ze sobą powiązane.
Istnieją zasadniczo trzy szkoły myślenia w sprawach dotyczących właściwego
miejsca reguł logiki aplikacji: umiejscowienie na serwerze, umiejscowienie
w oprogramowaniu klienta i umiejscowienie w oprogramowaniu pośredniczącym
(middleware). Oczywiście to, że aplikacja klient/serwer o nietrywialnym stopniu
złożoności wszystkie te podejścia pomiesza ze sobą, można uznać za dowiedziony
pewnik. Jest to tak pewne, jak z góry pewny jest podział tejże aplikacji na część
kliencką i część serwerową.
Niesłychane bogactwo wcieleń, jakie przybierać mogą reguły logiki aplikacji,
stanowi jedno z największych wyzwań dla zdroworozsądkowego programowania
systemów klient/serwer. Czasy prostego sprawdzanie poprawności danych
w systemie dBASE typu
@...SAY...GET
minęły już bezpowrotnie.
W rozdziale tym omówimy słabe i mocne strony każdego z tych podejść,
a następnie szczegółowo zgłębimy bazujące na serwerze reguły logiki aplikacji.
Nie miejmy złudzeń - przy budowaniu skomplikowanych aplikacji klient/serwer
będziemy nieuchronnie mieszać ze sobą implementacje reguł logiki aplikacji
w
programowaniu stacji roboczej klienta, serwera, i
być może nawet
implementacje tych reguł w oprogramowaniu pośredniczącym. Miejmy jednak
nadzieję, że oddzielne przebadanie każdej z
tych warstw przygotuje nas
w wystarczającym stopniu do naszego nowego zadania.
Ściślejsza definicja reguł logiki aplikacji
Przed omówieniem reguł logiki aplikacji realizowanych po stronie serwera
zdefiniujemy bardziej szczegółowo, czym w istocie są reguły logiki aplikacji.
Przeanalizujemy w tym celu rozmaite postacie, jakie reguły logiki aplikacji mogą
przybierać, i opowiemy o funkcji, jaką każda z nich pełni.
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
611
Skuteczne zaimplementowanie reguł logiki aplikacji zapewnia, że dane rezydujące
w bazie danych są zgodne z regułami i praktyką postępowania w danej organizacji.
Jednym ze sposobów osiągnięcia tego celu jest takie określenie każdej kolumny
w każdej tabeli bazy danych, by chroniła ona przed wprowadzeniem wartości
naruszających reguły organizacji. Z
perspektywy bazy danych oznacza to
zastosowanie wobec danych pewnych więzów lub ograniczeń (constraint),
zapewniających, że dane zawierać będą tylko poprawne wartości. To właśnie
przychodzi nam zwykle na myśl, gdy słyszymy termin reguły logiki aplikacji.
UWAGA:
W obrębie tego rozdziału terminów logiki aplikacji i ograniczenia lub więzy
używamy zamiennie. Ograniczenia są podstawową formą, jaką reguły logiki
aplikacji przyjmują w bazach danych i aplikacjach. Tak naprawdę to określenie
ograniczenia nigdy mi się nie podobało - niekiedy ograniczenia wcale nie
ograniczają. Czasami definiują wartości domyślne dla kolumn, czasami znów
ustanawiają relacje między tabelami. W tym rozdziale reguły logiki aplikacji
stosowane będą często w sposób generalny, jako odnoszące się do tych elementów
baz danych i aplikacji, które je implementują.
Jednak samo chronienie bazy danych przed niepoprawnymi wartościami jeszcze
nie wystarczy. Reguły logiki aplikacji, w odniesieniu do baz danych, spełniają
w rzeczywistości trzy niezależne zadania: nie dopuszczają niepożądanych danych
do bazy, definiują zależności między kolumnami i tabelami, oraz opisują sposób,
w jaki dane powstają w bazie. Każde z tych zadań omówię teraz oddzielnie.
Ograniczenia nie dopuszczają niepoprawnych danych do bazy danych. Definiują
także wartości domyślne dla kolumn, jeśli rzeczywiste wartości nie zostały
dostarczone. Przykładem takiego ograniczenia jest: „wszystkie faktury muszą
zawierać aktualną informację o kliencie”. Z punktu widzenia bazy danych
limitowałoby to - lub ograniczało - wartości, jakie mogą być przechowywane
w tabeli INVOICE. Innym przykładem ograniczenia mogłoby być: „wartości
w kolumnie
PaymentType
muszą pochodzić z następującej listy:
'C'
,
'H'
,
'R'
”. Ograniczenie, które definiuje wartość domyślną dla kolumny, może być
wyrażone jako: „domyślnym sposobem płatności jest gotówka”.
Definicje reguł logiki aplikacji mogą również określać zależności między tabelami
(na przykład „dla każdej faktury musi być przynajmniej jedna zamówiona
pozycja”) i wewnątrz-tabelowe zależności między kolumnami (takie jak „kolumna
Commission
w
tabeli SALES równa się kolumnie
AmountOfSale
pomnożonej przez .07”). Osobiście wolę unikać wewnątrz - tabelowych zależności
między kolumnami, obliczenia takie jak te wykonując zwykle na bieżąco, lecz są
pewne sytuacje, w których jest to niemożliwe. W tym przykładzie kolumna
Commission
jest zależna od kolumny
AmountOfSale
, zatem można by nie
612
Część IV
bez racji utrzymywać, iż takie uzależnienia uniemożliwiają dokonanie pełnej
normalizacji tabel.
Przy pomocy reguł logiki aplikacji można opisywać pochodzenie elementów
danych. Opis pochodzenia elementu wskazuje na jego źródło: gdzie dany element
bazy danych powstał, w jaki sposób został wyprowadzony, obliczony czy
wygenerowany? Czy jest on agregacją kolumny X w tabeli Y? Prostym
przykładem mogłoby tu być: „saldo „winien” księgi głównej jest uaktualniane
poprzez dodawanie do niego sum nowych transakcji „do wypłaty””. Definiuje to
pochodzenie lub źródło salda „winien” księgi głównej.
Jak już wspomniałem, lepiej jest unikać wyprowadzania jednego elementu danych
z innego. Nie twierdzę tym samym, że nie należy tego nigdy robić, lecz że trzeba
starannie rozważyć wszystkie możliwe konsekwencje. Wyprowadzanie jednego
elementu danych z innego tworzy zależność między nimi oboma. Może to być
nieuniknione, lecz może i doprowadzić do poważnych kłopotów. Jeśli dana
źródłowa ulegnie zmianie, to także i dana zależna musi zostać zmieniona. Zwykle
chronimy się przed tą niedogodnością implementując mechanizmy „księgowania”
(posting) danych. Dane, które zostały zaksięgowane, uaktualniają swe elementy
zależne (tak jak w przypadku salda „winien” księgi głównej) i jednocześnie
przestają być redagowalne. Po uaktualnieniu elementów zależnych żadne inne
modyfikacje nie są już dozwolone.
Teraz, gdy już nieco lepiej rozumiemy, czym są reguły logiki aplikacji,
zastanówmy się, jak najlepiej je zaimplementować. Jak już wspomniałem, istnieją
trzy szkoły w sprawie najodpowiedniejszego miejsca dla reguł logiki aplikacji.
Określenie zaś właściwego miejsca dla reguł logiki aplikacji wpływa silnie na
sposób, w
jaki zostaną zaimplementowane. Jeśli zaimplementujemy je na
serwerze, to oczywiście zrobimy to z pomocą ograniczeń i podobnych im środków.
Jeśli implementację reguł logiki aplikacji umiejscowimy w oprogramowaniu
klienta, to użyjemy do tego kodu programu. Jeśli zaś reguły logiki aplikacji
wbudujemy w
oprogramowanie pośredniczące, to trzeba będzie skorzystać
z narzędzi dostarczanych przez dany produkt.
Implementacje reguł logiki aplikacji na serwerze
Choć podejrzewam, że przemawia przeze mnie niepoprawny administrator baz
danych (DBA), to niezachwianie obstaję przy bazujących na serwerach
implementacjach reguł logiki aplikacji. Innymi słowy, w sprawach wdrażania reguł
logiki aplikacji zajmuję stanowisko „grubego serwera”. A oto podstawy mojej
filozofii:
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
613
Gdy to tylko możliwe, reguły logiki aplikacji należy umieszczać na serwerze
i w miarę konieczności uzupełniać w
oprogramowaniu pośredniczącym
(middleware) i w aplikacjach klienckich, w tej właśnie kolejności.
Oczywisty wniosek z tej zasady jest bardzo podobny:
Reguła logiki aplikacji zrealizowana po stronie klienta, która może być
przeniesiona do oprogramowania pośredniczącego lub serwera bazy danych,
powinna tam zostać „niezwłocznie” przeniesiona. Podobnie też każda reguła
logiki aplikacji osadzona w oprogramowaniu pośredniczącym, która może być
przeniesiona do serwera, powinna się tam znaleźć.
Sądzę, że przesłanki dla takiej filozofii staną się bardziej oczywiste, gdy omówimy
wszelkie „za” i „przeciw” dla wszystkie trzech wymienionych modeli.
Silne strony implementacji serwerowej
Jedną z korzyści z umieszczenia reguł logiki aplikacji na serwerze bazy danych
jest to, iż wówczas przed niepowołanym dostępem i przypadkowym uszkodzeniem
chronione są bezpośrednio same dane. Ponieważ tego rodzaju mechanizmy
kontrolne są wewnętrznie powiązane z
danymi, to bazujące na serwerze
ograniczenia gwarantują, że dane przechowywane w
bazie danych będą
zabezpieczone przed nieuprawnionym skasowaniem i zawsze zawierać będą
poprawne wartości.
Inna korzyść z implementowania reguł logiki aplikacji na serwerze polega na tym,
że wszystkie aplikacje klienckie, komunikujące się z bazą danych, uzyskują
automatyczny dostęp do reguł. Jednym z wielkich problemów, jakie stwarza
podejście polegające na lokowaniu reguł logiki aplikacji w oprogramowaniu
klienta jest to, że narzędzia programistyczne do tworzenia klientów są często
zależne od platformy i systemu operacyjnego. Przeciwnie z implementacjami
bazującymi na serwerze - wszyscy najważniejsi producenci systemów zarządzania
bazami danych (DBMS) typu klient/serwer dostarczają sposobów łączenia się
z klientami bazującymi na różnych systemach operacyjnych i różnych platformach
sprzętowych. Jakie by nie było środowisko systemu operacyjnego klienta, ma on
zarówno dostęp do informacji o regułach logiki aplikacji na serwerze bazy danych,
jak i musi się im podporządkować..
Inną zaletą implementowania reguł logiki aplikacji na serwerze jest prędkość.
Ponieważ na ogół instytucje traktują serwer bazy danych jako inwestycję
w infrastrukturę, to stosunkowo łatwo przychodzi im znalezienie pieniędzy na
kupno oprogramowania i sprzętu niezbędnego do tego, by serwer działał jak
należy. Jeśli umieszczenie reguł logiki aplikacji na serwerze pogorszyłoby
wyraźnie jego efektywność, to korporacja będzie z reguły bardziej skłonna zakupić
dodatkowe zasoby konieczne do skompensowania spadku niż umieścić na każdym
614
Część IV
biurku maszyny o dużej mocy, nawet jeśli koszt pierwszego rozwiązania
przekracza koszt drugiego.
Innym czynnikiem do uwzględnienia jest to, że serwery baz danych są z samej
swej konstrukcji skalowalne. Jeśli zatem nasze potrzeby przekraczają maksymalne
możliwości danej platformy sprzętowej, to serwer i jego bazę danych możemy
przenieść na silniejszą platformę sprzętową bez konieczności dokupowania DBMS
innego producenta lub przeprojektowywania naszej bazy danych. Ten sam rodzaj
skalowalności powinien występować w
oprogramowaniu pośredniczącym
i w rozwiązaniach bazujących na klientach, jeśli mają one stanowić porównywalną
alternatywę. Na razie jednak tak nie jest - gdy na przykład mamy oprogramowanie
klientów pracujące w systemie Windows, to nie oderwiemy się już od platformy
Intela. Wprawdzie Windows NT jest również dostępny na niewielkiej liczbie
innych platform, lecz nie jest on tak przenośny jak Sybase SQL Server, dostępny
dla prawie każdej liczącej się platformy sprzętowej i systemu operacyjnego.
Słabe strony implementacji serwerowej
Jedna ze słabości rozwiązań bazujących na serwerze wynika stąd, że wydajność
serwera bazy danych jest odwrotnie proporcjonalna do wielkości jego obciążenia.
W miarę jak do obiektów bazy danych dodawane są ograniczenia, dostęp do nich
(a szczególnie modyfikacje) musi stawać się coraz wolniejszy. Zjawisko to może
nabrać takiej ostrości, że serwer stanie się w praktyce bezużyteczny.
Odpowiedzią nie jest jednak pospieszne przerzucenie się na reguły logiki aplikacji
bazujące na klientach lub oprogramowaniu pośredniczącym. Tkwi ona raczej
w takim podejściu, jakie zwykle przyjmujemy, gdy nagły wzrost ilości danych
spowalnia serwer w
stopniu nie do przyjęcia - czyli w
zainwestowaniu
w dodatkowe zasoby sprzętowe i
programowe niezbędne do przywrócenia
serwerowi odpowiedniej mocy. Przecież w przypadku nagłego wzrostu woluminu
danych rezygnacja z serwera na rzecz rozwiązań bazujących na klientach nie jest
na ogół brana pod uwagę. To samo winno dotyczyć implementacji reguł logiki
aplikacji - ich implementacje na serwerach należy traktować jako integralną część
bazy danych i
podstawowy składnik serwera. Przy takim nastawieniu
przeforsowanie inwestycji niezbędnych do obsługi bazujących na serwerze
implementacji reguł logiki aplikacji stanie się o wiele łatwiejsze.
Inną słabą stroną, często wytykaną przez oponentów umieszczania reguł logiki
aplikacji na serwerach, jest skłonność tych implementacji do bazodanowej lub
serwerowej „egocentryczności”. Oznacza to, że przenoszenie reguł logiki aplikacji
pomiędzy bazami danych lub z serwera na serwer jest trudne lub wręcz
niemożliwe. Tabela w jednej bazie danych nie mogłaby przypuszczalnie odwołać
się do tabeli w innej bazie danych w celu sprawdzenia poprawności wprowadzanej
do kolumny pozycji, ani też tabela na jednym serwerze nie mogłaby uzyskać
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
615
wartości domyślnej z tabeli na innym serwerze. Ponieważ instytucje wykazują
skłonność do organizowania serwerów zgodnie ze strukturą swych działów, to
niewątpliwie stanowi to pewien problem.
Odpowiedzią na te zastrzeżenia jest (jednak!) skłonienie producentów DBMS do
poprawienia współpracy ich produktów z różnymi bazami danych i serwerami. Na
przykład Sybase już teraz obsługuje heterogeniczne zapytania do baz danych
(cross-database queries), tak jak zresztą robił to od lat. Co więcej, technologia
taka jak serwer replikacyjny w Sybase rozwiązuje problem wieloplatformowości,
pozwalając na automatyczne replikowanie kluczowych tabel z jednego serwera na
drugi. Natomiast technologia bram (gateway) serwerowych umożliwia zapytania
heterogeniczne. Pozwala ona na wykonywanie zapytań do tabel umieszczonych
w systemach DBMS różnych producentów tak, jakby wszystkie one były na
jednym serwerze. Odpowiedzią na zależność od bazy danych i od serwera nie jest
pospieszne przejście na jeszcze jedną niedojrzałą technologie, lecz wywieranie
nacisku na istniejących producentów po to, by swe narzędzia do obsługi
wielobazowości i
wieloplatformowości ulepszyli przynajmniej do stopnia
elementarnej użyteczności.
Innym problemem związanym z bazującymi na serwerach implementacjami reguł
logiki aplikacji jest występujący często brak integracji między oprogramowaniem
klienta a serwerem. Jednym ze skutków tej sytuacji bywa niekiedy niewłaściwe
obsługiwanie przez klienta komunikatów serwera związanych z regułami logiki
aplikacji, lub nawet całkowite ich ignorowanie.
Także i w tym przypadku odejście od implementacji serwerowych nie jest żadnym
rozwiązaniem. Wprost przeciwnie, rozwiązaniem jest właśnie wywarcie presji na
producentów narzędzi do tworzenia oprogramowania klienckiego (takich jak
Borland), by skłonić ich do dokonania pełnej integracji ze wspieranymi
systemami. Czyli - jeśli Delphi zapewnia obsługę określonego DBMS typu
klient/serwer - to obsługa ta powinna być pełna i musi obejmować wszystkie
związane z klientami mechanizmy, jakich platforma ta dostarcza, z wykrywaniem
naruszenia reguł logiki aplikacji włącznie.
Silne strony implementacji klienckiej
Jedną z silniejszych stron implementowania reguł logiki aplikacji na kliencie są
możliwości indywidualnego dostosowywania i spory zakres kontroli, dostępnej
w dziedzinie sygnalizowania i reagowania na reguły logiki aplikacji. Zupełnie
proste jest sterowanie przechodzeniem przez kolejne pola. Na przykład
uniemożliwienie użytkownikowi opuszczenia formularza, zanim wszystkie wpisy
nie będą poprawne, jest tu zwykle zagadnieniem banalnym.
616
Część IV
Inną zaletą implementowania reguł po stronie klienta jest elastyczność języków
programowania aplikacji, nieporównywalna z SQL. Na przykład Object Pascal jest
językiem bez porównania bogatszym niż SQL; nawet BASIC jest lepszy.
Ostatnią zaletą implementowania reguł logiki aplikacji na klientach jest możliwość
umieszczania ich w komponentach, których można potem ponownie używać we
wszystkich aplikacjach opracowanych z
użyciem tego samego narzędzia.
Dodawanie reguł logiki aplikacji do oprogramowania staje się wówczas równie
proste, jak „rzucenie” komponentu na formularz. W rozdziale 21, „Reguły logiki
aplikacji w aplikacjach Delphi”, opisano jak się to robi.
Słabe strony implementacji klienckiej
Podstawową niedogodnością związaną z umieszczeniem reguł logiki aplikacji
wyłącznie w oprogramowaniu klienta jest konieczność „obsadzania” w roli
klientów coraz to potężniejszych maszyn. W końcu komputery te zaczynają
wymagać zasobów tej miary, że ledwie parę lat temu wystarczyłyby one dla
dobrego serwera. W rezultacie na biurku ląduje najnowszy i najlepszy sprzęt, na
jaki nas stać, ponieważ klient nieustannie skarży się na niedostateczną moc
obliczeniową. Aplikacje klienckie, które obfitują w reguły logiki aplikacji,
pochłaniają więcej pamięci i działają wolniej niż te, które mają ich mniej. Odnosi
się to zwłaszcza do aplikacji, które dla obsłużenia swych bazujących na kliencie
implementacji muszą zapuszczać bazujące na serwerze zapytania. Jeśli dla
przykładu aplikacja kliencka musi zapytać swój serwer zapleczowy o typ danych
w pewnej kolumnie po to, by do jej danych mogła zastosować odpowiednie
ograniczenia, to niewątpliwie musi wykonać zbyt wiele pracy. Byłoby o wiele
lepiej, gdyby zadanie to pozwolono wykonać serwerowi, który przecież
z oczywistych powodów wie z góry, jak je wykonać.
Gdy budujemy aplikacje, które niepotrzebnie wypytują serwer o informacje
dotyczące ograniczeń, pojawia się problem „gadatliwej pielęgniarki”. Pielęgniarka
usiłuje wykonać zabieg chirurgiczny, lecz ponieważ jako pielęgniarka nie ma
wystarczających kwalifikacji, musi nieustannie zawracać głowę swej szefowej,
czyli chirurgowi. Ponieważ pani chirurg spędza swój cały czas pomagając
pielęgniarce, nie ma czasu na praktykowanie chirurgii. A ponieważ pielęgniarka,
choćby nie wiadomo jak dokładnie stosowała się do wskazówek chirurga, nie zrobi
niczego innego, czego nie zrobiłby chirurg, to cała ta praktyka chirurgiczna traci
wszelki sens. Jest to modelowy przypadek elementów, nie służących
zamierzonemu celowi - nie robiących tego, co robią najlepiej. Mamy tu do
czynienia z sytuacją, gdy w aplikacji klienta implementujemy reguły logiki
aplikacji, których właściwym miejscem są serwery baz danych.
Wraz z nieustannym rozbudowywaniem sprzętu klienta pojawiają się kłopoty
związane ze stale zmieniającymi się konfiguracjami sprzętowymi i programowymi.
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
617
W
trakcie historycznego rozwoju komputerów owo nieustające dostrajanie
i poprawianie sprzętu zostało „wyrzucone” na serwery, lecz nie stało się tak
w świecie „grubych klientów”. W ostatecznym efekcie otrzymamy więc serwer na
każdym biurku, wymagający do obsługi dodatkowego personelu i wiedzy.
Podejście to narusza również jeden z
podstawowych dogmatów filozofii
klient/serwer - dogmatu zmniejszonego zapotrzebowania na zasoby klienta.
Naturalną konsekwencją użycia DBMS typu klient/serwer jest - wedle
powszechnego mniemania - to, że klient może być mniej wydajny, ponieważ cała
rzeczywista praca związana z zarządzaniem bazą danych odbywa się na serwerze.
Jeśli zatem niezbędne jest powiększenie zasobów, to będzie to miało miejsce
przede wszystkim na serwerze, a nie na kliencie. Temu sposobowi myślenia
zaprzecza zaś wprost model „grubego klienta”.
Innym problemem związanym z wbudowywaniem reguł logiki aplikacji w klienta
jest to, że implementacje takie rzadko kiedy są ze swej natury niezależne od
narzędzia, o niezależności od producenta nie wspominając. Oznacza to, że trzeba
będzie ponownie „wynajdywać koła”, jeśli na przykład musimy stworzyć jedną
aplikację, która uaktualniać będzie pewną tabelę w Delphi w ciągu jednego
tygodnia, i drugą, która uaktualniać ją będzie w Developerze/2000 Oracla w ciągu
następnego tygodnia. Ponieważ Developer/2000 nie będzie miał dostępu do reguł
logiki aplikacji, które wbudowaliśmy w aplikację Delphi, to będziemy musieli
zaimplementować je ponownie korzystając z narzędzi Developera. Sytuacja
wygląda jeszcze gorzej, gdy uwzględnić należy możliwość pracy narzędziami
wywodzącymi się z
różnych platform. Prawdopodobnie będziemy w
stanie
hermetyzować reguły logiki aplikacji danego programu w zestawie komponentów
Delphi i następnie zestawu tego użyć zarówno w aplikacjach Delphi, jak i Borland
C++ Builder, i w ten sposób narzucić te same reguły logiki aplikacji w różnych
narzędziach. Lecz co stanie się, gdy te same reguły zechcemy wprowadzić do
programu znakowego C działającego w systemie Unix?
Wbudowanie reguł logiki aplikacji w oprogramowanie klienta zamiast do serwera
zamyka także możliwość oglądania z jednego punktu „obserwacyjnego” całości
reguł logiki aplikacji w bazie danych lub w banku danych. Ponieważ wszystkie te
reguły zamknięte są w kodzie programu lub w obiektach, nie można w prosty
sposób zobaczyć, jakie ograniczenia narzucono na jakie dane - czyli zupełnie
inaczej niż w podejściu opartym na serwerze. W końcu dochodzimy do tego, że
narzędzia CASE używamy jedynie w celu stwierdzenia, gdzie zaimplementowane
są nasze reguły logiki aplikacji.
Ostatnim argumentem, jaki można wysunąć na rzecz tezy o nieadekwatności
rozwiązań bazujących na klientach jest to, że nawet jeśli dana aplikacja lub
narzędzie izoluje bazę danych od niepoprawnych danych, to sama baza danych
pozostaje nadal nie chroniona. Rodzi to nadmierne uzależnienie od konkretnych
narzędzi do tworzenia oprogramowania klienckiego, które wcale nie tak łatwo
618
Część IV
osłabić. W efekcie cały dalszy rozwój oprogramowania klienckiego musi odbywać
się z pomocą tego samego narzędzia - w razie użycia innego dotychczasowe reguły
logiki aplikacji trzeba by albo w nim powielić, albo całkowicie zarzucić. Choć
producenci narzędzi nie mieliby z pewnością żadnego problemu z realizacją tej
pierwszej możliwości, to na przeszkodzie stoją względy strategii rynkowej.
Dlatego o wiele lepiej jest trzymać reguły logiki aplikacji na serwerze, gdzie mogą
być wdrażane bez względu na rodzaj narzędzia użytego w aplikacji klienckiej, oraz
przywoływane i współużytkowane przez wszystkie aplikacje, zgodnie z ich
przeznaczeniem.
Silne strony oprogramowania pośredniczącego
Termin middleware, czyli oprogramowanie pośredniczące, odnosi się do
oprogramowania znajdującego się między klientem a serwerem. W szczególności
middleware izoluje klientów od serwerów i serwery od klientów, zmuszając je do
komunikowania się ze sobą poprzez warstwę pośredniczącą. Na middleware może
składać się wszystko, co tylko da się umieścić między aplikacją klienta a serwerem
bazy danych. Może to być API realizujące przyłączanie do bazy danych, takie jak
BDE, lub może to być serwer aplikacji, taki jak serwer OLEnterprise, dołączony
do Delphi 3 Client/Server. Middleware może przyjmować kilka postaci. W sensie
czysto koncepcyjnym, podejście związane z middleware mogłoby być najlepszą
z dostępnych możliwości. W idealnym świecie reguły logiki aplikacji byłyby
zdefiniowane w obiektach systemu operacyjnego, które z kolei odwoływałyby się
do obiektów serwera bazy danych. Niektóre systemy operacyjne - na przykład
NeXTSTEP Steva Jobsa - posunęły się znacznie w tym kierunku.
Podejście wykorzystujące oprogramowanie pośredniczące pozwala uniknąć
doświadczanych aktualnie trudności z implementowaniem reguł logiki aplikacji na
różnych serwerach i różnych bazach danych, ponieważ reguły te nie rezydują ani
w danej bazie danych, ani na danym serwerze.
Podejście to pozwala także uchronić się przed problemem „grubego” klienta
i „grubego” serwera. W zasadzie ani serwer, ani klient nie będzie wtedy obarczony
obsługą reguł logiki aplikacji. Nie trzeba będzie inwestować w potężne biurkowe
PCety, zaś zasoby po stronie serwera zostaną zwolnione z
obowiązku
przestrzegania reguł logiki aplikacji.
Ograniczenia i
brokerzy danych w
Delphi dostarczają metody budowania
serwerów aplikacji, która jest zarazem efektywna i prosta w użyciu. Pozwala to
konstruować wielowarstwowe aplikacje klient/serwer równie łatwo, jak budowało
się w przeszłości aplikacje dwuwarstwowe. Więcej informacji na ten temat
znajdziemy w rozdziale 22, „Poza granicami modelu dwuwarstwowego”.
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
619
Słabe strony oprogramowania pośredniczącego
Największy problem z modelem opartym na oprogramowaniu pośredniczącym
polega na tym, że wymaga on zaprogramowania jeszcze jednej warstwy,
niezależnie od nieuniknionego trudu programowania serwera i klienta. Poza tym -
jako że nasze reguły logiki aplikacji nie będą już umieszczone w jednym miejscu -
nie będziemy mogli oglądać ich w jednej całościowej perspektywie. Innymi słowy,
ponieważ reguły te nie będą już znajdować się wyłącznie na serwerze lub
wyłącznie na kliencie (gdyż są rozproszone pomiędzy warstwami klienta,
oprogramowania pośredniczącego i
serwera), będą trudniejsze w
obsłudze
i administracji. Mamy zatem dwa problemy - podwójną pracę programistyczną,
gdyż wiele z reguł zaimplementowanych w oprogramowaniu pośredniczącym
trzeba będzie także zaimplementować na serwerze, i utrudnione zarządzanie
regułami biznesowymi naszej aplikacji, gdyż w omawianej architekturze są one
rozrzucone w kilku warstwach.
Implementowanie reguł logiki aplikacji bazujących na
serwerze
Teraz, gdy już przedstawiłem swoje poglądy na temat właściwej strategii reguł
logiki aplikacji, zastanówmy się, jak najlepiej je zaimplementować. Znalezienie
najodpowiedniejszego miejsca dla reguł logiki aplikacji w
dużej mierze
determinuje sposób, w
jaki zostaną zaimplementowane. Jeśli wybierzemy
implementację na serwerze, to niewątpliwie będziemy musieli stworzyć obiekty
bazy danych, realizujące naszą implementację. Poniższy podrozdział omawia tego
rodzaju obiekty i ich rolę w implementacji reguł logiki aplikacji.
Wprowadzenie
Pierwszym krokiem, jaki należy wykonać opracowując schemat reguł logiki
aplikacji, jest stworzenie modelu reguł przetwarzania, jakie nasza aplikacja ma
obsługiwać. Ów etap modelowania będzie bez wątpienia wymagał rozmów
i współpracy z użytkownikami. Prześledzenie wraz z użytkownikami wszystkich
ujmowanych w aplikacji reguł przetwarzania pozwoli zawczasu określić niezbędne
zależności między obiektami i wymagane ograniczenia dla bazy danych i aplikacji.
Dwa ogólne typy reguł logiki aplikacji, jakich będziemy poszukiwać, to reguły
zapewniające integralność domenową i
reguły zapewniające integralność
relacyjną. Integralność domenowa dotyczy rodzaju danych, które dana kolumna
może zawierać. Na przykład kolumna dat musi mieścić poprawne daty, a kolumna
typu „forma zapłaty” musi być ograniczona do gotówki, czeku lub karty
620
Część IV
kredytowej. Reguły logiki aplikacji związane z integralnością domenową mogą
być zaimplementowane z pomocą ograniczeń dla kolumn bazy danych.
Ograniczenia związane z integralnością relacyjną zapewniają przestrzeganie
zależności między tabelami. Na przykład, jeśli wiersz w tabeli FAKTURA
odwołuje się do wiersza w tabeli KLIENT, to ograniczenie integralnościowo-
relacyjne (lub referencyjne) zapewnia, że wiersz w tabeli KLIENT nie zostanie
skasowany tak długo, jak długo istnieć będzie jakiś odnoszący się do niego wiersz
w tabeli FAKTURA.
Na możliwie najwcześniejszym etapie prac należy wyczerpująco opracować
wszystkie reguły i wszystkie strategie, jakie można zastosować do analizowanych
danych. Najlepszym sposobem jest użycie prostych zdań napisanych w zwykłej
polszczyźnie. A oto niektóre przykłady reguł logiki aplikacji w języku naturalnym:
Każdy numer faktury w tabeli FAKTURA musi być niepowtarzalny.
Każdy numer klienta w tabeli FAKTURA musi mieć odpowiadający mu wiersz
w tabeli KLIENT.
Akceptowanymi kartami kredytowymi są VISA, MasterCard i American
Express.
Dla każdego wiersza-pozycji faktury obliczana jest suma częściowa przez
pomnożenie ceny pozycji przez zamówioną ilość.
Sumę ogólną faktury otrzymuje się przez dodanie wszystkich sum częściowych
w wierszach pozycji, oraz dodanie 7 procent podatku od sprzedaży i 5 dolarów
na koszty wysyłki i manipulacji.
Rekordu nagłówka faktury nie można skasować tak długo, jak długo istnieje
jakiś odpowiadający mu rekord szczegółowy faktury.
Domyślną metodą wysyłki wyrobów jest Federal Express.
Należy przyglądnąć się wszystkim kolumnom we wszystkich tabelach. Każda
z kolumn może zawierać tylko poprawne dane. Należy określić i zagwarantować
zachowanie zależności między tabelami. Trzeba zawczasu zaprojektować każdą
agregację i
wszystkie źródła danych. Zleceniodawca powinien sprawdzić
poprawność i kompletność listy reguł jeszcze zanim rozpoczniemy właściwą pracę.
Później, gdy będziemy tworzyć ograniczenia przeznaczone do umieszczenia
w projekcie bazy danych, może po kolei „odfajkowywać” każdą regułę logiki
aplikacji na liście. Sumienność na tym etapie zaoszczędzi nam czasu (i kłopotów)
później.
Wiele narzędzi CASE oferuje istotne wsparcie w implementowaniu reguł logiki
aplikacji. W popularnych narzędziach CASE klient/serwer występuje wszystko co
trzeba, począwszy od możliwości wpisywania zdań w
języku naturalnym,
opisujących reguły logiki aplikacji, aż po definiowanie szablonów procedur
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
621
zdarzeń w celu ich zaimplementowania. Jeśli musimy określić dużą ilość reguł
logiki aplikacji w skomplikowanym modelu bazy danych, to dobre narzędzie
CASE może zaoszczędzić wiele godzin pracy.
Ograniczenia PRIMARY KEY
Ograniczenia dla kolumn i
tabel są najczęściej używanym sposobem
implementowania bazujących na serwerze reguł logiki aplikacji. Choć prawdą jest,
że procedury zdarzeń (trigger) mogą zrobić wszystko to, co robią ograniczenia,
a nawet jeszcze więcej, to moją filozofię w debacie „ograniczenia kontra
wyzwalacze” ująłbym następująco:
Ograniczenia mają zawsze pierwszeństwo nad procedurami zdarzeń. Należy
zawsze starać się, by jak największa część implementacji naszych reguł logiki
aplikacji wykonana została z
użyciem ograniczeń. Resztę załatwić można
z pomocą perspektyw (view), procedur zdarzeń lub procedur pamiętanych (stored
procedure) - i
to w
tej właśnie kolejności. Perspektywy powinny mieć
pierwszeństwo przed procedurami zdarzeń, zaś procedury zdarzeń przed
procedurami pamiętanymi.
Ograniczenia są lepsze od wyzwalaczy, ponieważ są od nich szybsze. Przyczyną
jest to, że ograniczenia są narzucane przez samo jądro serwera (zwykle kod C
skompilowany dla danej platformy). Natomiast procedury zdarzeń składają się
z półskompilowanego SQL. Kod maszynowy jest prawie zawsze szybszy od kodu
półskompilowanego. Z tego też powodu perspektywy są korzystniejsze od
procedur zdarzeń. Składnia WITH CHECK OPTION w perspektywach ANSI SQL
jest wdrażana przez sam serwer, a nie przez SQL. Mimo to procedury zdarzeń są
bardziej zalecane od procedur pamiętanych, ponieważ realizowane są
automatycznie. Wbudowywanie reguł logiki aplikacji w procedury pamiętane
pozostawia zawsze to niebezpieczeństwo, że jakiś proces może pominąć procedurę
i zmodyfikować obsługiwaną przez nią tabelę, obchodząc w
ten sposób
obowiązujące w teorii reguły logiki aplikacji.
Pierwszym typem ograniczeń, jakie należy zastosować, są klucze pierwotne.
Określają one, które kolumny w tabeli jednoznacznie identyfikują każdy z wierszy.
Klucz pierwotny jest domyślną metodą dostępu do tabeli. Przykładami kluczy
pierwotnych są: pole InvoiceNumber w
tabeli INVOICE lub pole
CustomerNumber w tabeli CUSTOMER. Dodając klucz pierwotny nakazujemy
serwerowi sprawdzanie, czy wartości wstawiane do kolumny lub kolumn klucza
pierwotnego są unikalne w obrębie tabeli. Choć zwykle klucze pierwotne
definiujemy przy tworzeniu tabeli, to może się niekiedy zdarzyć, że zrobimy to już
po fakcie. Składnia SQL służąca do dodawania kluczy pierwotnych do istniejącej
tabeli wygląda następująco:
ALTER TABLE CUSTOMER ADD PRIMARY KEY (CustomerNumber)
622
Część IV
Ograniczenia FOREIGN KEY
Ograniczenia w formie kluczy obcych są bardzo popularne przy definiowaniu
relacji między tabelami. Wymagają one, by wartość umieszczana w kolumnie
jednej tabeli istniała wcześniej w innej tabeli. W podobny sposób uniemożliwiają
one usuniecie danej z drugiej tabeli, jeśli do danej tej odwołuje się pierwsza
tabela. Ograniczeń w formie kluczy obcych używamy na przykład po to, by mieć
gwarancję, że wszystkie numery klientów wylistowane w polu CustomerNumber
tabeli INVOICE istnieją w tabeli CUSTOMER. Odwołanie do obcego klucza
tworzymy zwykle w trakcie konstruowania tabeli, lecz nie jest wcale wykluczone,
że będziemy musieli zaczekać i zrobić to później. A oto składnia SQL służąca do
dodawania klucza obcego post factum:
ALTER TABLE ORDERS ADD FOREIGN KEY (CustomerNumber) REFERENCE
➥
CUSTOMER
Ograniczenie CHECK
Innym typem ograniczenia jest ograniczenie kontrolne (check). Zapewnia ono, że
wartość wstawiana do kolumny, występuje w pewnym zbiorze ustalonych
wcześniej wartości. Przypuśćmy, że pewne przedsiębiorstwo sprzedaży detalicznej
akceptuje tylko niektóre karty kredytowe, na przykład VISA, MasterCard
i American Express. Ponieważ jest to stały zbiór wartości, jest on dobrym
kandydatem na ograniczenie kontrolne. Możemy je zakodować jako ograniczenie
CHECK
używając następującej składni SQL:
ALTER TABLE ORDERS ADD CONSTRAINT INVALID_CREDIT_CARD
CHECK (CreditCardType in (‘V’, ‘M.’, ‘A’))
Ograniczenia kontrolne można również skonstruować w trakcie tworzenia tabeli.
Oto przykład:
CREATE TABLE NYSE_EVENTS
(
EventNo
INTEGER NOT NULL,
Year
INTEGER NOT NULL CHECK (YEAR >= 1799),
Description
VARCHAR(80) NOT NULL,
Resolution
VARCHAR(80) NOT NULL,
PRIMARY KEY (EventNo)
);
Ograniczenia kontrolne można definiować na poziomie tabel lub, jak
w poprzednim przykładzie, dla poszczególnych kolumn.
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
623
Wartości domyślne
Wartości domyślne dla pól mają istotne znaczenie, ponieważ określają wartość,
jaką kolumna otrzyma w operacji
INSERT
, jeśli wartość ta nie zostanie
dostarczona jawnie. Podawanie wartości domyślnych pozwala zagwarantować, że
dana kolumna wiersza otrzyma już w
momencie utworzenia poprawnie
wprowadzone dane.
Wśród programistów występuje tendencja do określania wartość domyślnych
kolumn z pomocą kodu programu. Można na przykład w łatwy sposób przypisać
kolumnie taką wartość korzystając ze zdarzenia
OnNewRecord
w Delphi.
Jednak jakby to nie było łatwe, definiowanie wartości domyślnych dla kolumn
w aplikacji jest niedobrą praktyką. Wymaga ona na przykład „przekopania” się
przez kod programu w celu znalezienia wartości domyślnych dla kolumn tabeli.
O wiele lepszą metodą jest przechowywanie ich na serwerze, gdzie mogą być
łatwo odczytywane i zmieniane.
Choć niektórzy producenci dostarczają specyficznych dla platform sposobów
ustalania wartości domyślnych dla kolumn, to osobiście wolę pozostać przy
składni ANSI. Zaś składnia ANSI do ustalania wartość domyślnych dla kolumn
jest następująca:
ALTER TABLE ORDERS
ADD CreditCardType char(1)
DEFAULT ‘V’
Perspektywy
Istnieją sytuacje, w których implementację konkretnej reguły logiki aplikacji
najlepiej wykonać za pośrednictwem perspektywy SQL. Ujmując rzecz krótko,
perspektywa jest wyrażeniem
SELECT
języka SQL, które można skompilować
i „odpytywać” tak, jak gdyby była to najzwyklejsza tabela. Jest wiele różnych
sposobów korzystania z perspektyw, zaś podstawowy sposób ich użycia przy
implementowaniu reguł logiki aplikacji polega na wykonywaniu obliczeń na
kolumnach tabeli. Mamy tu na przykład perspektywę do obliczania sum
częściowych dla poszczególnych wierszy faktury:
CREATE VIEW INVOICEDETAIL
AS
SELECT InvoiceNumber, LineNumber, PriceEach * UnitsOrdered
➥
ExtendedTotal
Perspektywa ta implementuje regułę logiki aplikacji brzmiącą: „dla każdej pozycji
w wierszu faktury oblicza się sumę mnożąc cenę tej pozycji przez zamówioną
ilość”.
624
Część IV
Procedury zdarzeń
Gdy wszystko inne zawiedzie, musimy zwrócić się do procedury zdarzenia. Wiele
platform oferuje specjalne rozszerzenia języka SQL, nadające procedurom zdarzeń
i w ogólności procedurom różne nadzwyczajne możliwości. Na przykład Sybase
dostarcza Transact-SQL, natomiast Oracle zawiera PL./SQL. Jeśli to tylko
możliwe, należy zamiast procedur zdarzeń używać więzów. Jeśli tego, czego
potrzebujemy, nie możemy zrobić przy użyciu więzów, to wedle wszelkiego
prawdopodobieństwa załatwi nam to procedura zdarzenia. Oto przykład procedury
zdarzenia, która wykracza poza zwykle możliwości ograniczeń kolumnowych:
CREATE TRIGGER ORDERSInsert FOR ORDERS BEFORE INSERT AS
BEGIN
IF (New.CreditCardType=’V’ AND New.Amount<50.00) THEN
EXCEPTION
BELOW_MINIMUM_VISA;
END
Procedura ta zapewnia, że zamówienia zrealizowane przy pomocy karty
kredytowej VISA wynosić będą w sumie 50 $ lub więcej. Ze względu na
warunkowy charakter tej reguły, byłoby trudne lub wręcz niemożliwe
zaimplementować ją jako proste więzy kolumny. Zatem użycie procedury
zdarzenia w tej sytuacji jest jak najbardziej wskazane.
Procedury pamiętane
W pewnych kręgach „sequelowskich” daje się zauważyć dążność do nadużywania
procedur pamiętanych przy implementowaniu reguł logiki aplikacji. Wyraża się
przy tym pogląd, że procedur pamiętanych należy używać do wszystkich operacji
DML (Data Manipulation Language), tworząc dla każdej tabeli oddzielne
procedury
INSERT
,
UPDATE
i
DELETE
. Dopiero procedura taka zapewnia, że
przy każdej operacji przestrzegane są odpowiednie ograniczenia spójnościowe
i reguły logiki aplikacji.
Problem z takim podejściem polega jednak na tym, że uniemożliwia ono oglądanie
zabezpieczeń i implementacji reguł logiki aplikacji w naszej bazie danych
z jednego punktu „obserwacyjnego”. Redukuje także do zera użyteczność narzędzi
takich jak Delphi, ponieważ ich zdolność do wiązania obiektów programu
z
elementami bazy danych pozostaje wówczas w
przeważającej mierze
niewykorzystana. Wprawdzie z pamiętanych procedur DML można skorzystać za
pośrednictwem komponentu Delphi
TUpdateSQL
, to sposób ten w dużej mierze
marnuje korzyść wynikającą ze stosowania narzędzi takich jak Delphi -
umiejętność automatycznego podłączania się do danych, bez względu na ich
strukturę. Musimy bowiem odwzorowywać struktury naszych tablic w związanych
z nimi procedurach, czyli robić dokładnie to, czego próbowaliśmy uniknąć dzięki
narzędziom RAD takim jak Delphi.
Rozdział 20 Reguły logiki aplikacji na serwerze bazy danych
625
Poza tym tworzenie dla każdej tabeli w bazie danych przynajmniej trzech procedur
pamiętanych sprawia, że zarządzanie bazą staje się znacznie trudniejsze. W bazach
danych z tysiącami tabel możemy dojść do wielu tysięcy procedur pamiętanych.
Utrzymywanie ich jest dla DBA koszmarem i nieustannym źródłem zgryzoty.
Przyrost wydajności, uzyskiwany z budowania procedur pamiętanych w taki
„poszatkowany” sposób, jest przereklamowany i ma miejsce jedynie w pewnych,
bardzo szczególnych okolicznościach, a przy tym jest zwykle minimalny lub nawet
w
ogóle niedostrzegalny. Zwykle kłopoty związane z
tworzeniem procedur
pamiętanych w ogromnych ilościach są nieporównanie większe niż takie to
problematyczne korzyści.
Należy przy tym pamiętać, że pamiętane procedury, implementujące poprawność
danych, muszą być debugowane i obsługiwane tak, jak każdy inny program. Jeśli
w jakiejś tabeli pojawią się nieprawidłowe dane, to pierwszą rzeczą będzie
sprawdzenie, czy nie ma błędów w jej procedurach. W efekcie staniemy wobec
konieczności obsługiwania, prócz właściwego kodu Delphi, także i obszernego
zestawu skądinąd zbędnych procedur pamiętanych.
Z tych to względów odradzałbym konstruowania niepotrzebnych procedur
pamiętanych. Strońmy od tworzenia procedur przy byle okazji - używajmy ich
tylko w sytuacjach, w których ani tradycyjne więzy, ani procedury zdarzeń nie
mogą znaleźć zastosowania.
Przykładem takiej sytuacji jest „niesławny” podprogram księgowania. Jeśli
chcielibyśmy zakumulować wartości w
kolumnie lub kolumnach w
celu
zaksięgowania ich w oddzielnej tabeli, to ponieważ chcielibyśmy dokładnie
kontrolować moment, w którym takie zaksięgowanie nastąpi, zrobilibyśmy to
najprawdopodobniej z pomocą procedury pamiętanej.
Rozważmy przytoczony wcześniej przykład księgi głównej. Gdybyśmy musieli
napisać procedurę pamiętaną, obsługującą księgowanie transakcji „do wypłaty”
w księdze głównej, to moglibyśmy napisać coś takiego jak:
CREATE PROCEDURE POSTAP (APACCOUNT)
AS
DECLARE VARIABLE APTOTAL FLOAT
BEGIN
SELECT SUM(AmountOfTransaction) TranAmount
INTO
:APTOTAL
FROM
APTRANS
UPDATE GLBAL SET APMonthEndBalance=APMonthEndBalance+
➥
:APTOTAL
WHERE
AccountNumber=:APACCOUNT;
END
Procedura ta definiuje kolumnę
APMonthEndBalance
jako powstającą
z kolumny
AmountOfTransaction
w tabeli APTRANS. Implementuje ona
626
Część IV
regułę logiki aplikacji definiującą, w jaki sposób każdego miesiąca uzyskiwany
jest bilans strony „winien” w księdze głównej.
Procedury pamiętane przydają się w sytuacjach podobnych do tej, ponieważ mogą
one wykonać tyle instrukcji SELECT, ile jest niezbędnych do pełnego wykonania
całej operacji, a także i dlatego, że to my decydujemy, kiedy będą wykonane.
Szczególnie dobrze przystosowane są do operacji wsadowych, takich jak
podprogramy księgowania i generowanie złożonych raportów.