I.
Wprowadzenie do  języków zapytań (1)
  Wstęp
  1. Co to są języki zapytań?
  2. Znaczenie języków zapytań
  3. Zastosowania języków zapytań
  4. Własności języków zapytań
  Podsumowanie
  Zadania
II.
Wprowadzenie do  języków zapytań (2)
III.
Pojęcia obiektowości w bazach danych (1)
IV.
Pojęcia obiektowości w bazach danych (2)
V.
Podstawy semantyczne języków zapytań
VI.
Modele składu obiektów
VII.
Stos środowisk, rezultaty zapytań, funkcja nested
VIII.
Język SBQL (Stack-Based Query Language) (1)
IX.
X.
Dalsze własności SBQL
XI.
Operatory order by i group by
XII.
Przetwarzanie struktur nieregularnych
XIII.
Rozszerzenie języków zapytań o konstrukcje imperatywne
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

1. Co to są języki zapytań?

Jak zwykle w tak burzliwie rozwijającej się dziedzinie technologicznej, nie istnieje jednoznaczna definicja, co to znaczy „język zapytań”. Zdarzają się autorzy, którzy używają fraz takich jak „zapytanie w C++” (podając następnie pół-stronicowy kod przypominający szyfr), co jest nieporozumieniem co do charakteru i roli języka zapytań.

Początkowa idea języków zapytań polegała na stworzeniu prostego języka dla powszechnego użytkownika, umożliwiającego wyszukiwanie i inne proste operacje w bazie danych. Jednakże w trakcie rozwoju tej klasy języków okazało się, że kwestia „prostego języka” nie jest łatwa. Trudno np. twierdzić, że SQL-92 zaimplementowany (zazwyczaj częściowo) w systemach relacyjnych jest „prosty”, jeżeli weźmiemy pod uwagę setki stron jego dokumentacji. Książka Meltona i Simona na temat SQL [Melt93], która wyjaśnia wszystkie jego aspekty, liczy 536 stron. Tym bardziej trudno jest twierdzić, że SQL-99 [Melt99, Melt01] jest „prostym językiem”, ponieważ - o ile jakakolwiek firma zaimplementuje go w całości (co jest bardzo wątpliwe) - jego dokumentacja będzie miała kilka tysięcy stron i będzie to prawdopodobnie jeden z najbardziej skomplikowanych języków, jakie stworzyła ludzkość. Książka [Melto01] na jego temat liczy 928 stron. Kurs nauki tego języka bez najmniejszych wątpliwości musiałby trwać miesiące, jeżeli nie lata.

W literaturze na temat języków zapytań można znaleźć następujące punkty widzenia na ich istotę:

  • Proste, przyjacielskie i naturalne interfejsy dla powszechnego użytkownika. Języki zapytań służą do interakcyjnego formułowania zleceń wyszukiwania informacji w bazie danych lub jej aktualizacji przez mało doświadczonego użytkownika. W tę kategorię wpadają takie języki, jak interakcyjny SQL i QUEL (historyczny język systemu Ingres), języki oparte na formularzach, np. Query-By-Example i QBF, oraz różnorodne graficzne języki zapytań. W ostatnich latach, wskutek znacznego podwyższenia przyjacielskości interfejsów użytkownika, nastąpiła ewolucja poglądów. Większość specjalistów uważa obecnie, że języki takie jak SQL nie nadają się dla powszechnego użytkownika, gdyż w tej roli znacznie lepsze są interfejsy graficzne oparte na okienkach, menu, tabelech, przeglądaniu, nawigacji w grafie itp.

  • Warianty języków matematycznych teorii. Języki zapytań są użytkowymi wariantami języków znanych i sławnych matematycznych teorii, np. logiki matematycznej. Ten punkt widzenia był do pewnego czasu lansowany przez teoretyków baz danych. Obecne języki zapytań zaprzeczają tego rodzaju poglądom. Doszukiwanie się w SQL (szczególnie w SQL-99, OQL itd.) związków z algebrą relacji lub logiką matematyczną jest demagogią przypominającą bajkę A.Fredry o Cyganie gotującym zupę na gwoździu, gdzie algebra relacji lub logika pełnią rolę gwoździa. Teorie te przykrywają nikłą część koncepcji i semantyki tych języków. Zdaniem autora, w ostatnich latach rozwój języków zapytań został w znacznym stopniu sparaliżowany przez fałszywe koncepcje i stereotypy mające swoje źródło w logice matematycznej i teoriach związanych z modelem relacyjnym.

  • Podjęzyki bardzo wysokiego poziomu zanurzane w języki programowania. Podjęzyków tych można używać do wyszukiwania w bazie danych i do prostych aktualizacji. Są one zanurzane (embedded) w typowe języki programowania. W tej roli najczęściej występuje SQL. Ta filozofia jest pochodną kontrowersyjnej ideologii zakładającej, że dostęp do bazy danych powinien odbywać się w „nieproceduralnym podjęzyku”, który nie musi posiadać pełnych możliwości języka programowania. Zaletą jest to, że programiści mogą używać popularnych języków programowania, zaś interfejs do bazy danych jest (teoretycznie) niezależny od języka programowania. W praktyce zaleta ta jest iluzoryczna. Jak się okazało, tego rodzaju zanurzenie języka zapytań w język programowania jest obarczone poważnymi wadami, które określa się zbiorczo wspomnianym wyżej mianem „niezgodności impedancji”. Zanurzenie to wymaga warstwy pośredniczącej (specjalnych deklaracji, dodatkowej składni, kursorów/iteratorów, specjalnych struktur danych), która umożliwia interakcję z językiem programowania. Ta warstwa jest dodatkowym obciążeniem pamięci i czasu programistów oraz źródłowego i wynikowego kodu (chociaż niekoniecznie jest obciążeniem czasu wykonania). Warstwa ta ma negatywny wpływ na pielęgnacyjność (maintainability) całości oprogramowania.

  • Konstrukcje programistyczne (wyrażenia) bardzo wysokiego poziomu zintegrowane z językiem programowania. Zdania języka zapytań są obudowane konstrukcjami programistycznymi (imperatywnymi) czyniąc z języka zapytań kompletny interfejs do programowania aplikacji. Przykładem tego podejścia jest PL/SQL systemu Oracle oraz liczne tzw. języki czwartej generacji (4GL), często dodatkowo oparte na programowaniu wizyjnum i zdarzeniowum (visual programming, event-driven programming). Różnica z poprzednim podejściem polega na tym, że w tym przypadku tworzony jest nowy język lub narzędzie programowania, nie mający precedensów w klasycznych językach. Tego rodzaju narzędzia umożliwiają bardzo efektywną produkcję aplikacji, co zadecydowało o ich sukcesie. Ostatni punkt widzenia zakłada pojawienie się nowego rodzaju języka programowania, w którym występują specyficzne wyrażenia (podobne do klasycznych wyrażeń języka oprogramowania), zwane „zapytaniami”. Istotą tych nowych wyrażeń jest obsługa typów masowych (bulk), inaczej kolekcji, niekoniecznie przechowywanych w bazie danych. W tej roli języki zapytań są wyższym szczeblem abstrakcji nad konstrukcjami organizującymi pętle (while, repeat, goto, for, loop itp.), iteratorami, kursorami i innymi tego rodzaju udogodnieniami.
Zapytania koncepcyjnie „hermetyzują” pętle iteracyjne w języku programowania za pomocą operatorów, takich jak selekcja, projekcja, złączenie, unia, przecięcie, kwantyfikatory, grupowanie, sortowanie itp.

Słowo „koncepcyjnie” jest tu istotne, gdyż chodzi o taką hermetyzację, która jest naturalna, zrozumiała i czytelna dla programisty; wspomagająca procesy modelowania pojęciowego przy tworzeniu aplikacji. Przykładowo, zapytanie w SBQL:

P1.1.

Pracownik where Wiek > 30

w klasycznym języku programowania musiałoby być zrealizowane za pomocą pętli while, for lub innej, gdzie w każdej iteracji sprawdzany byłby warunek Wiek > 30, patrz np. następujący pseudo-kod:

P1.2.

TypPracownicy wynik = Æ;
TypPracownik bieżącyPracownik = getFirst(Pracownicy);
while (bieżącyPracownik != Null) {
      if (bieżącyPracownik.Wiek > 30) {
            wynik = wynik È (SetOf) bieżącyPracownik;
      };
      bieżący_pracownik = getNext(Pracownicy);
};

W tej koncepcji języki zapytań są tworami całkowicie ortogonalnymi w stosunku do cechy trwałości danych (czyli bazy danych). Język zapytań nie musi być dedykowany do obsługi bazy danych: zapytania mogą łączyć odwołania do bazy danych i odwołania do tymczasowych danych/obiektów powołanych przez programistę dla potrzeb danej aplikacji. Tę własność miał również zanurzony SQL, którego zapytania mogły zawierać odwołania do zmiennych programistycznych (np. w C) poprzez specjalną składnię (poprzedzający dwukropek).

Powstałe w ten sposób języki zapytań znoszą granicę pomiędzy trwałymi i nietrwałymi danymi oraz kolekcjami i indywidualnymi danymi. Chyba pierwszym powszechnie znanym tego rodzaju językiem był DBPL stworzony na Uniwersytecie w Hamburgu (bazujący na koncepcji języka Modula-2) [Matt92, Schm94]. DBPL pozostawia jednak wyrażenia i zapytania jako różne pojęcia. Mniej znany, ale nieco wcześniejszy Loqis [Subi90, Subi91] jest zbudowany na podobnej zasadzie, ale całkowicie znosi różnicę pomiędzy wyrażeniami a zapytaniami. SQL-99 również mieści się w tej kategorii języków (jakkolwiek wątpliwości dotyczą jego inżynierskiej sensowności).

Spełnienie tej zasady oznacza zniesienie granicy pomiędzy tym, co w klasycznych językach zapytań określano jako „wyrażenie” i zapytaniem. Przykładowo, typowe wyrażenia, takie jak 2+2, (x*y - z)/32 stają się w ten sposób szczególnymi przypadkami zapytań i mogą być składnikami zapytań, takich jak np.

P1.3.

select Zarobek + (x*y - z)/32 from Pracownik where Wiek > 30

gdzie Pracownik, Zarobek, Wiek są nazwami odnoszącymi się do bazy danych, zaś x, y, z są zmiennymi języka programowania.

Świadomość odnośnie do tego, że tak naprawdę zapytania są uogólnieniem wyrażeń języka programowania, z trudem przebija się w świecie przemysłowym. Np. w Oracle PL/SQL oraz językach 4GL istnieje jeszcze ten tradycyjny podział. Niekiedy jest on motywowany optymalizacją zapytań, ale wydaje się, że ta motywacja nie powinna hamować koncepcji. Jeżeli zaakceptowana będzie koncepcja, wówczas znajdą się pieniądze na to, aby ktoś opracował metody optymalizacyjne dla tej nowej sytuacji. Jedynym problemem nakreślonego wyżej podejścia jest konieczność opracowania, zaimplementowania i wylansowania nowego języka programowania. Popularny stereotyp mówi, że w obecnych czasach (gdzie funkcjonują setki języków programowania) jest to trudne i związane z dużymi nakładami na implementację, wdrożenie i promocję. Praktyka pokazuje inny obraz: każdy pojawiający się nowy system jest wyposażany we własny język programowania, zaś różnych języków nazwanych SQL jest tyle, ile działających systemów. Według naszej wiedzy, żaden zaimplementowany SQL nie trzyma się sztywno standardów SQL, które zresztą posiadają liczne luki specyfikacyjne. W tej sytuacji uleganie pewnej marketingowej histerii odnośnie do niemożliwości wylansowania nowego języka, a już szczególnie nabożne trzymanie się SQL-owskiego lukru „select...from...where...”, jest nierozsądne, wręcz niemądre, szczególnie jeżeli dotyczy to prototypów i działalności badawczej.

W podejściu stosowym (jak również w tym wykładzie) przyjmujemy ostatni z wymienionych punktów widzenia. Jakkolwiek rola języka zapytań jako środka dla nieprofesjonalistów jest istotna, może być zrealizowana poprzez ograniczenie możliwości języka oraz obudowanie go bardziej przyjacielską składnią lub wizyjnym interfejsem. Dla nas istotny jest jednak język zapytań o pełnych możliwościach, który może być podstawą profesjonalnych technologii programistycznych. Nie zważając na obecne tendencje przemysłowe przyjmiemy punkt widzenia, w którym zapytania są uogólnionymi wyrażeniami programistycznymi znoszącymi podział na dane trwałe (zapisane w bazie danych) i dane ulotne (będące własnością danej aplikacji) oraz podział na dane masowe (kolekcje) i dane indywidualne (pojedyncze zmienne).

Copyrights © 2006 PJWSTK
Materiały zostały opracowane w PJWSTK w projekcie współfinansowanym ze środków EFS.