7 SYSTEMOWE ASPEKTY JljZYKA SQL I
PRZYKŁAD 7.9
Funkcja z rys. 7.5 zostanie przepisana tak, aby krotki były przeglądane od ostatniej wprzód. Najpierw należy określić kursor kursorDyr jako przewi-jalny, co osiąga się przez dopisanie słowa kluczowego SCROLL w wierszu 6):
6} EXEC SQL DECLARE dyrKursor SCROLL CURSOR FOR 7) SELECT cenaSieci FROM FilmDyr;
Wczytywanie krotek trzeba zainicjować przez instrukcję fetch las?, a w pętli skorzystać z instrukcji FETCH prtor. A zatem instrukcje z wierszy od 9) do 15) z rys. 7.5 przyjmą następującą postać:
F.XEC SQŁ FETCH LAST FROM dyrKursor IN70 :cena; while(l) {
/* to samo co w wierszach 11) do 15) */
EXEC SQL FETCH PRIOR FROM dyrKursor INTO :cer.a;
}
Mylne jest przekonanie, że czytanie krotek w kolejności odwrotnej niż są one generowane przez zapytanie:
SELECT cenaSieci FROM FilmDyr
ma jakiekolwiek zalety. W rzeczywistości analizowanie ich w kolejności odwrotnej jest jeszcze kosztowniejsze, ponieważ zazwyczaj są one wygenerowane wszystkie jeszcze zanim zostaną po raz pierwszy udostępnione kursorowi dyrKursor.
□
Prezentowany model łączenia SQL z innymi programami polega na osadzaniu zapytań i innych poleceń SQL w programach zapisanych w języku podstawowym. Istnieje jeszcze inny tryb zanurzania SQL w innym języku. Instrukcje SQL mogą bowiem być przetwarzane bezpośrednio w języku podstawowym. Nic są one znane w czasie kompilacji ani nie są obsługiwane przez preprocesor, ani przez inny kompilator.
Takim przykładem może być program, który interakcyjnie pobiera zapytanie w języku SQL, czyta je, a następnie przetwarza. Można tu przypomnieć interpreter zapytań SQL, o którym była mowa w rozdziale 5. W każdym komercyjnym systemie SQL taki interpreter istnieje. Jeżeli zapytania są czytane i wykonywane w trakcie przetwarzania, to podczas kompilacji nic się nie dzieje. Należy po prostu dokonać rozbioru składniowego zapytania i określić właściwy sposób jego wykonania w języku SQL zaraz po przeczytaniu zapytania.
Program zapisany w języku podstawowym musi pobrać tekst, przekazać go do systemu SQL jako poprawną instrukcję, a następnie ją wykonać. Tym celom służą dwie instrukcje dynamicznego SQL.
1. F.XEC SQL PREPARE, po którym umieszcza się zmienną, np. V, słow'o kluczowe FROM, a następnie zmienną lub wyrażenie z języka podstawowego o typie tekstowym. Tekst jest traktowany jako instrukcja SQL i stanowi on wartość zmiennej V. Najczęściej podlega on rozbiorowi składniowemu, a SQL określa sposób wykonania, natomiast przetwarzanie nie zachodzi.
2. EXEC SQL EXECUTE, po którym wymienia się nazwę zmiennej z punktu 1, np. V. Ta instrukcja powoduje przetworzenie instrukcji SQL zapisanej w zmiennej.
Można oba etapy wykonać jako jeden, jeśli skorzysta się z instrukcji
EXEC SQL EXECUTE IMMEDIATE
po której umieszcza się zmienną tekstową, wyrażenie tekstowe lub zmienną dzieloną. Wada tego rozw iązania ujawnia się, jeśli chcemy to samo zapytanie przetwarzać wielokrotnie w różnych kontekstach. Korzystając z EXECU?E IMMEDIATE, za każdym razem trzeba ponieść koszt przygotowania instrukcji, podczas gdy przy rozwiązaniu dwuetapowym przygotowanie odbywa się Wiko jeden raz.
PRZYKŁAD 7.10
Na rysunku 7.7 umieszczono szkic programu w języku C, który pobiera ze standardow-ego wejścia tekst do zmiennej zapytanie, analizuje to zapytanie,
1) void czytaj Zapytanie( ){
2) EXEC 5QL BEGIN DECLARE SECTION;
3) char *zapytanie;
4) £XEC SQL END DECLARE SECTION;
5) /* pobranie cri użytkownika zapytania, alokacja
pamięci (np. wywołanie malloc) i przygotowanie zmiennej dzielonej :zapytanie, które wskazuje na pierwszy znak zapytania */
6) EXEC SQL PREPARE SOLzapytanie EROM :zapytanie;
7) EXEC SQL EXECUTE SOLzapytanie;
)
RYSUNEK 7.7
Przygotowanie oraz uruchomienie zapytania SQL