Języki i Środowiska Programowania Baz Danych | |||||||||||||||||||
|
3. Konstrukcje w języku zapytań obsługujące dane nieregularne Jeżeli dana o nazwie n jest nieobecna w pewnym obiekcie z identyfikatorem i, wówczas nested(i) nie będzie zawierać bindera o nazwie n. Zatem jeżeli mamy zapytanie o postaci Powstaje pytanie, co z takim pustym zbiorem programista może zrobić. Rozważmy przykład:
przy czym atrybut Zar może nie wystąpić w niektórych obiektach Prac. W tej sytuacji można przyjąć że jeżeli Zar nie wystąpi, to predykat Zar > 1000 przyjmuje wartość fałsz. Alternatywnie można przyjąć, że jest to sytuacja błędna powodująca podniesienie wyjątku. Pierwsze założenie prowadzi do licznych niespójności (identycznych z tymi, które były przyczyną krytyki wartości zerowych), zatem je bezwzględnie odrzucamy. Pozostaje tylko druga interpretacja, czyli przyjęcie, że zapytanie to jest błędne. Jeżeli programista oczekuje, że atrybut Zar może nie istnieć, to powinien tę sytuację przewidzieć w swoim zapytaniu. Np. przyjmując, że funkcja count działa również na indywidualnych elementach zwracając dla nich 1, może formułować to zapytanie w sposób następujący:
Najpierw sprawdza, czy Zar istnieje, następnie upewniwszy się, że istnieje, używa po where odpowiedniego predykatu. Przypominamy, że funkcja exists(q) zwraca true, jeżeli zapytanie q zwraca choć jedną wartość, i false w przeciwnym przypadku. Zwrócimy uwagę, że w tej sytuacji nie byłoby poprawne pozornie identyczne zapytanie
gdyż wymagałoby specjalnego trybu ewaluacji operatora and, mianowicie takiego, w którym drugi człon nie podlegałby ewaluacji, jeżeli pierwszy człon zwróciłby false (taka interpretacja jest powszechna w językach programowania). W językach zapytań taka interpretacja mogłaby prowadzić do błędów ze względu na optymalizację zapytań, która w wyniku metod przepisywania może przestawić kolejność predykatów. Analogicznie, przyjmując, że kwantyfikatory działające na indywidualnym elemencie traktują go jako zbiór jednoelementowy, można to samo zapytanie sformułować z pomocą kwantyfikatora:
Pierwsze zapytanie zwraca referencje do obiektów pracowników, którzy mają zarobek przekraczający 1000. Drugie zapytanie, oprócz ww. referencji, zwraca także referencje do tych obiektów Prac, w których atrybut Zar jest nieobecny (kwantyfikator ogólny działający na pustym zbiorze zawsze zwraca prawda). Jak widać, dane nieregularne w SBQL nie wymagają wprowadzania wartości zerowych ani też nowych konstrukcji gramatycznych (poza drobnym doprecyzowaniem semantyki funkcji count i kwantyfikatorów). Istotne w naszej metodzie jest również to, że nieobecna dana (czyli odpowiednik wartości zerowej) może być dowolnie złożona, np. Adres. Taka sytuacja nie jest wyrażalna w modelu i systemach relacyjnych. Są one w stanie wyrazić sytuację, że każdy atrybut w ramach danej Adres ma wartość zerową, ale semantycznie nie jest to równoważne sytuacji, w której cała dana Adres ma wartość zerową. Przyjęta przez nas interpretacja nieobecnych danych jest także spójna z funkcjami agregowanymi. Rozpatrzmy podany przez Ch.Date przykład z SQL, w którym jeżeli relacja R(A, B) posiada atrybuty A i B z wartościami zerowymi, to w generalnym przypadku zapytania
mogą zwrócić różny wynik. W SBQL problem ten nie występuje, ponieważ syntaktyczny odpowiednik pierwszego zapytania SQL, mający postać sum(R.(A+B)), jest błędny. Nie można operatora + stosować do pustego zbioru. Poprawny semantyczny odpowiednik pierwszego zapytania ma w SBQL postać:
W zapytaniu tym powołano dwie nazwy pomocnicze a i b poprzez operator as. Jeżeli pewien obiekt R nie zawiera atrybutu A lub nie zawiera atrybutu B, to podzapytanie (A as a, B as b) zwróci pusty wynik, wobec czego do liczenia a+b nie dojdzie; będzie ono policzone wyłącznie dla tych obiektów, w których występują oba atrybuty. Odpowiednik drugiego zapytania ma postać:
|
||||||||||||||||||
Copyrights © 2006 PJWSTK Materiały zostały opracowane w PJWSTK w projekcie współfinansowanym ze środków EFS. |