I.
Wprowadzenie do  języków zapytań (1)
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.
  Wstęp
  1. Operatory niealgebraiczne
  2. SBQL - przykłady zapytań i porównania
  Podsumowanie
  Zadania
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ń

 

2. SBQL - przykłady zapytań i porównania

Niżej zaprezentujemy przykłady użycia wprowadzonych operatorów, które zilustrują sposób ich użycia dla uzyskania określonego celu wyszukiwania. Przykłady będą odnosić się do baz danych, których schematy są przedstawione na Rys.55. Staraliśmy się, aby przedstawiony tam schemat relacyjny i schemat obiektowy (w nieco zmodyfikowanym UML) były równoważne w sensie zawartości informacji w bazie danych. Oczywiście, schematy te nie są i nie mogą być semantycznie równoważne w sensie informacji dostarczanych dla użytkownika tych schematów oraz narzucanych ograniczeń. Np. schemat relacyjny nic nie mówi o tym, że każdy dział musi zatrudniać co najmniej jednego pracownika i musi mieć co najmniej jedną lokację, nie ustala, że usunięcie danej pracownika implikuje usunięcie jego adresu itd. Informacje te są reprezentowane explicite w schemacie obiektowym. Na ogół przykłady będą odwoływać się do schematu obiektowego. Odwołania do schematu relacyjnego będą wyraźnie zaznaczone.

P9.9.

Podaj pełną informację o pracownikach:

Prac

Jest to odpowiednik zapytania SQL:

P9.10.
SQL:

select * from Prac

Lukier select ... from ... where ... był w latach 70-tych motywowany "przyjaznością" języka dla powszechnego, przypadkowego użytkownika. Od tego czasu zmieniło się nastawienie do tej klasy języków zapytań: większość specjalistów uważa, że język taki jak SQL nie nadaje się dla końcowego użytkownika, który oczekuje raczej graficznych interfejsów w postaci menu, słów kluczowych, prostych nawigacji itd. Użytkownikami języków takich jak SQL, OQL i SBQL są i będą w przyszłości głównie programiści. Dla tej klasy użytkowników powyższy lukier syntaktyczny jest zbędny, przeszkadzający ortogonalności języka i prowadzący do mało czytelnych zbitek językowych typu "select select * from select * from ..." itd. W przypadku SBQL rezygnujemy z tego lukru. Jest to umotywowane głównie abstrakcyjną składnią SBQL, ale motywacja dla pozbycia się tego lukru jest jak najbardziej praktyczna, co pokażemy na następnych przykładach.

Zwróćmy uwagę na różnice semantyczne: zapytanie SQL zwraca całą tabelę Prac, podczas gdy nasze zapytanie zwraca referencje do wszystkich obiektów Prac. Podkreślimy, że zapytania w SBQL nie zwracają obiektów, lecz referencje do obiektów.

55
Rys.55. Schemat bazy danych, na której wykonano poniższe zapytania

P9.11.

Podaj nazwiska wszystkich pracowników:

Prac . Nazwisko

Jest to odpowiednik zapytania SQL:

P9.12.
SQL:

select Nazwisko from Prac

Istnieje różnica semantyczna pomiędzy zapytaniem SQL a zapytaniem SBQL. Zapytanie SQL zwraca jednokolumnową tablicę stringów będących nazwiskami, natomiast zapytanie SBQL zwraca podobną tablicę, ale referencji do podobiektów Nazwisko w obiektach Prac. Do tej tablicy można oczywiście zastosować operator dereferencji, który zamieni tę tablicę na tablicę stringów. Jednakże tablica referencji jest bardziej uniwersalna niż tablica stringów, w szczególności może być użyta po lewej stronie operacji podstawienia, tj. poprzez tę tablicę można aktualizować podobiekty Nazwisko. Ponieważ dereferencja prowadzi do straty informacji, wobec czego dla jej wykonania musi być wyraźny powód, np. konieczność wykonania funkcji print.

P9.13.

Podaj pełną informację o Kowalskim:

Prac where (Nazwisko = 'Kowalski')

Jest to odpowiednik zapytania SQL:

P9.14.
SQL:

select * from Prac where Nazwisko = 'Kowalski'

W odróżnieniu od SQL, zapytanie w SBQL zwróci referencję do obiektu Kowalskiego. Referencję tę można następnie "skonsumować" zdaniem imperatywnym; np. można usunąć obiekt Kowalskiego zdaniem

P9.15.

delete Prac where (Nazwisko = 'Kowalski');

W dalszych przykładach będziemy często rezygnować z nawiasów, przyjmując naturalne reguły pierwszeństwa operatorów.

P9.16.

Podaj zarobek Kowalskiego:

(Prac where Nazwisko = 'Kowalski') . Zar

Jest to odpowiednik zapytania SQL:

P9.17.
SQL:

select Zar from Prac where Nazwisko = 'Kowalski'

W odróżnieniu od SQL, zapytanie w SBQL zwróci referencję do zarobku Kowalskiego. Referencję tę można następnie "skonsumować" zdaniem imperatywnym; np. można zmienić zarobek Kowalskiego poprzez zdanie imperatywne dokonujące podstawienia:

P9.18.

((Prac where Nazwisko = "Kowalski") . Zar ) := 5000;

Odpowiada to zdaniu aktualizacyjnemu SQL:

P9.19.
SQL:

update Prac set Zar = 5000 where Nazwisko = 'Kowalski'

Do kwestii zanurzania zapytań SBQL w zdania imperatywne wrócimy w następnych rozdziałach.

P9.20.

Numery i nazwiska pracowników zarabiających więcej niż 1000:

(Prac where Zar > 1000) . (NrP, Nazwisko)

Wynikiem zapytania jest bag struktur struct{iNrP, iNazwisko}, gdzie w każdej strukturze pierwsza referencja dotyczy atrybutu NrP, zaś druga - atrybutu Nazwisko. (NrP, Nazwisko) jest konstruktorem struktury wprowadzonym uprzednio. Zapytanie posiada następujący odpowiednik w SQL:

P9.21.
SQL:

select NrP, Nazwisko from Prac where Zar > 1000



P9.22.

Zwróć referencję do danej pointerowej PracujeW dla pracownika Kowalskiego:

(Prac where Nazwisko = "Kowalski") . PracujeW

 

Zapytanie to oczywiście nie ma odpowiednika w SQL. Nie ma także odpowiednika w OQL. Zapytanie takie ma jednak sens, gdyż może być podzapytaniem szerszego zapytania (patrz następny przykład). Również zapytanie to ma sens z powodu operacji aktualizacyjnych, które chcielibyśmy zbudować na bazie języka zapytań. Wielu twórców obiektowych języków zapytań zapomina, że referencje (pointery) są też danymi, które mogą podlegać aktualizacji. Np. aby przenieść Kowalskiego do działu Sprzedaż, należałoby podstawić na tę daną pointerową identyfikator działu Sprzedaż. W systemie Loqis (z dokładnością do składni) takie zdanie ma postać:

P9.23.

(Prac where Nazwisko = "Kowalski") . PracujeW := ref(Dział where Nazwa = "Sprzedaż");

Z lewej strony operatora podstawienia oblicza l-wartość (l-value), czyli referencję do danej pointerowej PracujeW w obiekcie Kowalskiego, zaś z prawej strony podstawienia mamy r-wartość (r-value), która jest referencją do działu Sprzedaż. Oczywiście, takie podstawienie mogłoby być automatycznie skojarzone z odpowiednimi operacjami na bliźniaczych pointerach Zatrudnia obiektów Dział (tak jak w standardzie ODMG, wiązania do C++ i Java).

P9.24.

Podaj pełne dane o dziale, w którym pracuje Kowalski:

((Prac where Nazwisko = "Kowalski") . PracujeW ) . Dział

Zapytanie to zwraca referencję do obiektu działu, w którym pracuje Kowalski. Odpowiednikiem tego zapytania w OQL jest:

P9.25.
OQL:

select d from Prac as p, p.PracujeW as d
where p.Nazwisko = "Kowalski"

Jakkolwiek OQL unika nazwy Dział, uważamy, że z dwóch powodów jest to niewłaściwe. Jak pokazuje poprzedni przykład, istnieje potrzeba rozróżnienia pomiędzy referencją do pointera prowadzącego do obiektu a referencją do samego obiektu. Po drugie, zapytanie w SBQL jest bardziej czytelne, gdyż explicite używa nazwy Dział, oznaczającej końcowy efekt ewaluacji.

P9.26.

Podaj nazwę działu, w którym pracuje Kowalski:

(Prac where Nazwisko = "Kowalski").PracujeW.Dział.Nazwa

Zapytanie to zwraca referencję do nazwy działu, w którym pracuje Kowalski. Odpowiednik tego zapytania w OQL:

P9.27.
OQL:

select  p.PracujeW.Nazwa from Prac as p
where p.Nazwisko = "Kowalski"

Przykład ilustruje tzw. wyrażenia ścieżkowe (path expressions), czyli "gładką" nawigację wzdłuż pewnej ścieżki wyznaczonej schematem wzdłuż powiązań pointerowych i/lub w dół hierarchii obiektów. W podejściu stosowym wyrażenia ścieżkowe pojawiły się jako efekt uboczny podanych definicji - w istocie operator kropki pozostaje nadal binarnym operatorem niealgebraicznym, zaś powyższe wyrażenie SBQL należy czytać jako:

P9.28.

(((Prac where Nazwisko = "Kowalski").PracujeW).Dział).Nazwa

Wyrażenia ścieżkowe mogą być dowolnie długie, np.:

P9.29.

Podaj nazwisko szefa Kowalskiego:

(Prac where Nazwisko = "Kowalski") . PracujeW . Dział . Szef . Prac . Nazwisko

Dzięki temu, że nie definiujemy specjalnych wyrażeń ścieżkowych (jak w pracach [Kim89, Kife92, Chri96]), lecz wykorzystujemy do tego celu standardowo operator kropki, uzyskujemy możliwość dowolnego kombinowania wyrażeń ścieżkowych z innymi operatorami. To daje nam podstawę, aby twierdzić, że zdefiniowane przez nas wyrażenia ścieżkowe są bardziej uniwersalne niż propozycje, które spotkaliśmy w literaturze (pomijając fakt, że owe propozycje nie mają najczęściej dobrze zdefiniowanej formalnej semantyki). Przykładowo, poniższe wyrażenie SBQL:

P9.30.

(Prac where ("budynek D" Î (PracujeW . Dział . Lokacja))) . (Nazwisko, (Adres . Miasto))

specyfikuje nazwisko i miasto zamieszkania pracownika pracującego w dziale, którego jedną z lokacji jest budynek D.

ODMG OQL ogranicza możliwość używania wygodnych wyrażeń ścieżkowych poprzez niezbyt rozsądny w tym kontekście lukier select...from...where... oraz poprzez przyjęcie (również niezbyt rozsądnego) założenia, że operator kropki może się pojawić tylko wtedy, jeżeli wyrażenie przed kropką zwraca dokładnie jedną wartość. Obydwa te założenia są oczywiście odrzucone przy definiowaniu operatorów niealgebraicznych.

P9.31.

Podaj wszystkie informacje o pracownikach zarabiających więcej od Kowalskiego:

Prac where Zar > ((Prac where Nazwisko = "Kowalski").Zar)

Zapytanie to ilustruje możliwość zagnieżdżania zapytań. W zapytaniu tym występuje dwa razy nazwa Zar, ale dzięki stosowej semantyce każde z tych wystąpień jest inaczej wiązane: pierwsze Zar jest wiązane na wierzchołku stosu posiadającego dwie sekcje, natomiast drugie Zar jest wiązane na wierzchołku stosu posiadającego trzy sekcje. Podobne zapytanie w SQL ma postać:

P9.32.
SQL:

select * from Prac where Zar > select Zar from Prac where Nazwisko = "Kowalski"


P9.33.

Dla każdego pracownika zwróć pełną informację o pracowniku i jego dziale:

Prac join (PracujeW . Dział)

W zapytaniu tym skorzystaliśmy z operatora zależnego złączenia. Wynikiem jest bag struktur struct{ iPrac, iDział }, gdzie pierwszy składnik każdej struktury jest referencją do obiektu pracownika, zaś drugi jest referencją do obiektu jego działu. Zapytanie to ma odpowiednik w OQL:

P9.34.
OQL:

select  struct(pr: p, dz: d) from Prac as p, p.PracujeW as d

Nie jest to dokładny odpowiednik, ponieważ w OQL struktury muszą mieć etykiety (prdz w powyższym zapytaniu), a ponadto specyfikacja OQL jest na tyle nieprecyzyjna, że nie wiadomo, co tak naprawdę zwróci takie zapytanie (OQL nie wprowadza pojęcia referencji).

Analogiczne zapytanie odnoszące się do struktury relacyjnej ma postać:

P9.35.

Prac join (Dział where PracujeW = NrD)

lub (z użyciem konstruktora struktur, mającego skutek iloczynu kartezjańskiego):

P9.36.

(Prac, Dział) where PracujeW = NrD

To zapytanie ma odpowiednik w SQL:

P9.37.
SQL:

select * from Prac, Dział where PracujeW = NrD

Nie jest to dokładny odpowiednik, ponieważ wynikiem nie jest bag z parami referencji (jak w przypadku SBQL), lecz zbiorcza tabela wartości zawierająca zarówno atrybuty tabeli Prac, jak i tabeli Dział.

P9.38.

Podaj informację o działach i średnich zarobkach pracowników w działach:

Dział join avg(Zatrudnia.Prac.Zar)

Wynikiem zapytania jest bag struktur struct{ iDział, średni_zar }, gdzie pierwszy składnik każdej struktury jest referencją do obiektu Dział, zaś drugi jest liczbą będącą średnią zarobków w tym dziale. Rys.56 przedstawia stany stosu środowisk przy wiązaniu poszczególnych nazw występujących w tym zapytaniu. Zwróćmy uwagę, że po nazwie Prac występuje nawias, który powoduje usunięcie górnej sekcji stosu środowisk. Jest on następnie znowu podwyższany przez następujący po tej nazwie operator kropki. Analogicznie w innych podobnych sytuacjach.

W OQL zapytanie to wymaga użycia opcji group by, która niestety została wyspecyfikowana nieprecyzyjnie (toteż nie mamy pewności jak jej użyć).
W przypadku schematu relacyjnego podobne zapytanie można sformułować  za pomocą następującego zdania SQL:

P9.39.
SQL:

select d .*, avg(p.Zar) from Dział as d, Prac as p
where d.NrD = p.PracujeW   group by d.Nrd

Wadą jest konieczność użycia operatora group by, który jest mało ortogonalny w stosunku do innych operatorów, prowadzi do nowego jakościowo warunku (having), ma rafy semantyczne oraz sprawia trudności z optymalizacją zapytań. W przypadku SBQL unikamy tego wątpliwego operatora, zastępując go innymi operatorami lub ich kombinacją. Analogiczne zapytanie w SBQL dla struktury relacyjnej przyjmie następującą postać (opcja group by jest niepotrzebna):

P9.40.

Dział join avg((Prac where PracujeW = NrD ). Zar)

lub z pomocniczymi nazwami:

P9.41.

(Dział as d) join avg(((Prac as p) where p.PracujeW = d.NrD). p.Zar)


P9.42.

Podaj średnią liczbę pracowników w poszczególnych działach:

Dla schematu obiektowego:
avg( Dział . count(Zatrudnia))

Dla schematu relacyjnego:
avg( Dział . count(Prac where NrD = PracujeW))

 

56
Rys.56. Poglądowy obraz stanów stosu środowisk przy wiązaniu nazw w zapytaniu Dział join avg(Zatrudnia.Prac.Zar)

Analogiczne zdanie w standardzie SQL-89 można wyrazić z pomocą dodatkowej perspektywy. W standardzie SQL-92 zdanie to można sformułować za pomocą opcji group by. Opcja ta prowadzi do znanej rafy semantycznej, polegającej na tym, że jeżeli pewien dział nie będzie miał ani jednego pracownika, wówczas nie zostanie uwzględniony przy obliczaniu średniej. W przypadku SBQL ta anomalia nie występuje.

P9.43.

Dla pracowników zarabiających więcej niż 2000 pracujących w dziale zlokalizowanym w budynku A podaj nazwisko, stanowisko, nazwę działu i nazwisko szefa działu:

((Prac join (PracujeW.Dział)) where Zar>2000                 
and
"Bud A" Î Lokacja).(Nazwisko, Stan, Nazwa, (Szef.Prac.Nazwisko))

Wynikiem będzie kolekcja struktur struct{iNazwisko1, iStan, iNazwa, iNazwisko2 }, gdzie każda struktura zawiera cztery referencje odpowiednio do atrybutów Nazwisko(pracownika), Stan (stanowisko pracownika), Nazwa (działu pracownika) oraz Nazwisko (jego szefa).

P9.44.

Czy to prawda, że w każdym dziale jest pracownik zarabiający więcej od swojego szefa?

" Dział ( $ Zatrudnia.Prac ( Zar > Szef.Prac.Zar))

Wynikiem zapytania jest wartość boolowska prawda lub fałsz. Kwantyfikatory są operatorami niealgebraicznymi, wobec czego (jak w całym SBQL) użycie nazw pomocniczych (czyli "zmiennych związanych kwantyfikatorami") nie jest konieczne. Jeżeli zachodziłaby potrzeba, wówczas takie "zmienne" można byłoby powołać; np. powyższe zapytanie może mieć postać:

P9.45.

" Dział as x ( $ x.Zatrudnia.Prac as y ( y.Zar > x.Szef.Prac.Zar))

Powyższe zapytania nie mają odpowiedników w SQL, ponieważ konstruktorzy tego języka nie przewidzieli, że zapytania SQL mogą zwracać wartości boolowskie. W OQL ostatnie zapytanie przyjmie postać:

P9.46.
OQL:

for all x in Dział :
    exists y in  selectfrom x.Zatrudnia as z :
        y.Zar > select t.zar from x.Szef as t

Na tym przykładzie Czytelnik może wyrobić sobie pogląd, czy lukier syntaktyczny select...from... oraz forsowanie użycia pomocniczych "zmiennych" mają sens. Dla porównania, pierwsze zapytanie w SBQL ma 17 elementów leksykalnych. Analogiczne zapytanie w OQL ma 32 elementy leksykalne. Które z tych zapytań jest bardziej zrozumiałe?

Zgodnie z diagramem z Rys.55 adres pracownika jest daną opcyjną i złożoną. W terminologii modelu relacyjnego, brak adresu dla pracownika oznacza, że w tym miejscu jest zapisana wartość zerowa (null). Wartości te wymagają w SQL specjalnych opcji, które (jak omawialiśmy wcześniej) są niespójne oraz komplikują semantykę i pragmatykę języka. W naszym podejściu będziemy ich unikać. Podany dalej przykład w SBQL pokazuje, że zamiast operacji na wartościach zerowych można zastosować kwantyfikatory.

P9.47.

Podaj pracowników, którzy na pewno mieszkają w Olsztynie:

Prac where $ Adres (Miasto = "Olsztyn")

Gdyby nam zależało na pracownikach, którzy albo na pewno mieszkają w Olsztynie, albo być może mieszkają w Olsztynie, ponieważ ich adres jest nieznany, wówczas można zastosować następujące zapytanie:

P9.48.

Podaj pracowników którzy na pewno lub być może mieszkają w Olsztynie:

Prac where " Adres (Miasto = "Olsztyn")

Kwantyfikator uniwersalny działający na pustym zbiorze zwróci true.

Z podanych przykładów wynika, że sporo artykułów poświęconych problemowi wartości zerowych było spowodowane brakiem zrozumienia charakteru tego zjawiska językowego. Zaowocowało nieudanymi próbami opanowania go przez specjalne logiki wielowartościowe, algebry i inne twory formalnych.

Niżej zilustrujemy kilka stylów tworzenia zapytań, które są konsekwencją przyjętych przez nas definicji.

P9.49.

Podaj nazwiska i zarobki projektantów zarabiających więcej od swoich szefów:

Styl SQL (schemat relacyjny):

(((Prac as x) , (Dział as y) , (Prac as z))
where x.Stan = "projektant" and x.PracujeW = y.NrD
and y.Szef = z.NrP and x.Zar > z.Zar).(x.Nazwisko, x.Zar)

Analogiczne zdanie SQL jest uderzająco podobne:

P9.50.

select x.Nazwisko, x.Zar 
from Prac as x, Dział as y, Prac as
where x.Stan = 'projektant' and x.PracujeW = y.NrD
and y.Szef = z.NrP and x.Zar > z.Zar

Styl OQL (schemat obiektowy):

P9.51.

((Prac as x) join (x.PracujeW.Dział as y) join (y.Szef.Prac as z)
where x.Stan = "projektant" and x.Zar > z.Zar).(x.Nazwisko, x.Zar)

Analogiczne zdanie OQL:

P9.52.
OQL:

select x.Nazwisko, x.Zar
from Prac as x, x.PracujeW as y, y.Szef as
where x.Stan = "projektant" and x.Zar > z.Zar

Wariant minimalny SBQL (schemat obiektowy):

P9.53.

(Prac where Stan = "projektant" and Zar > (PracujeW.Dział.Szef.Prac.Zar)).(Nazwisko, Zar)

Styl "rachunku dziedzinowego" zapisanego w SBQL (schemat relacyjny):

P9.54.

(((Prac.(Nazwisko as np,Zar as zp, Stan as sp, PracujeW as dp)),
(Dział.( Nrd as nd, Szef as sd)), (Prac.(Zar as zs, NrP as ns)))
where
sp = "projektant" and dp = nd and sd = ns and zp > zs).(np, zp)

Poprzez te przykłady chcemy pokazać, że stare debaty o "wyższości rachunku krotkowego nad rachunkiem dziedzinowym" oraz obecny spór o to, czy struktury obiektowe są lepsze czy gorsze od struktur relacyjnych (jeżeli chodzi o języki zapytań), można pogodzić. Istotne jest, jakie struktury danych dopuszczamy w systemie zarządzania bazą danych, natomiast z chwilą przyjęcia tych struktur można dla nich zbudować język zapytań na gruncie podejścia stosowego. Tym samym wykazujemy, że rozpowszechniona w Internecie teza M. Stonebrakera o tym, że dla modeli obiektowych nie można zbudować języka zapytań, jest nonsensem albo raczej grą zmierzającą do wytworzenia fałszywego stereotypu w świecie komercyjnym i zdobycia przez to niezasłużonej przewagi pewnej opcji technicznej (systemów obiektowo-relacyjnych) na rynku. Struktury obiektowo-relacyjne nie mają w tym względzie jakiejkolwiek przewagi nad strukturami obiektowymi.

Będziemy bronić tezy dokładnie odwrotnej. Modele obiektowo-relacyjne zwiększają liczbę opcji w strukturach danych (poprzez eklektyzm i wprowadzenie opcji redundantnych), a każda nowa opcja w strukturach danych musi być obsługiwana przez język zapytań. Konsekwencją jest wzrost złożoności języka zapytań, przy czym nie jest to wzrost liniowy (proporcjonalny do wzrostu opcji w strukturach danych). Zgodnie z zasadą korespondencji, każda nowa własność języka musi pociągać za sobą konieczność ustalenia jej interakcji z już istniejącymi własnościami. To oznacza, że złożoność składni i semantyki języka rośnie co najmniej w kwadracie w stosunku do złożoności modelu danych. Tym tłumaczymy fakt, że opis standardu SQL-99 osiągnął parę tysięcy stron, i nadal są narzekania, że jest niekompletny i niejasny. Biorąc pod uwagę optymalizację zapytań, można powołać się na powszechnie znany efekt skali, który oznacza zależność wykładniczą pomiędzy rozmiarem specyfikacji problemu a złożonością jego zaimplementowania (patrz np. metoda szacowania złożoności oprogramowania COCOMO). Efekt skali powoduje, że złożoność optymalizatora języka zapytań będzie prawdopodobnie rosła szybciej niż trzecia potęga złożoności modelu danych. Tym tłumaczymy dość powszechną obecnie opinię, że całkowite zaimplementowanie SQL-99 jest niemożliwe. Uważamy to za bezpośrednie skutki demagogii uprawianej przez niektóre osoby z kręgów komercyjno-industrialnej relacyjnej konserwy.

Gorąca debata ideologów świata komercyjnego odnośnie do tego, który paradygmat języków zapytań jest lepszy, na gruncie semantyki podejścia stosowego ma charakter sporu religijno/ideologicznego, jest demagogicznym pustosłowiem pozbawionym istotnych merytorycznych argumentów. Dotyczy to szczególnie tych przypadków, w których obrońcy pewnej koncepcji powołują się na jej "zdrowe podstawy matematyczne": w dziedzinie baz danych jest to od lat niezawodny sygnał taniej demagogii.

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