Język SQL w Delphi

advertisement
Język SQL w Delphi
1. Kwerendy
Kwerenda jest zleceniem dla programu bazy danych, mającym na celu odszukanie rekordów
spełniających określone kryteria. Przykładem kwerendy może być zlecenie odszukania rekordu
zawierającego dane osoby o podanym nazwisku lub odszukaniu wszystkich osób pochodzących
z jednego miasta. Wyniki obydwu zapytań są różne. W pierwszym przypadku uzyskujemy jeden rekord,
a w drugim całą ich grupę.
Język SQL (ang. strucured query language) został zaprojektowany przez firmę IBM w celu sprawnej
realizacji kwerend w relacyjnych bazach danych.
Do wykonania kwerendy w Delphi służy komponent TQuery. Jej podstawowe właściwości:
❏
❏
❏
❏
SQL — Zawiera tekst komendy języka SQL, która zostanie wykonana.
DatabaseName — Określa nazwę bazy danych, z którą skojarzony został zbiór danych.
Params — Zawiera parametry przekazywane do komendy SQL.
Active — Określa czy zbiór danych jest otwarty, czy nie.
1.1. Przygotowanie do ćwiczenia
Aby wykonać ćwiczenie związane z zastosowaniem komponentu TQuery, należy utworzyć nową
aplikacjię i dodać do formularza komponent TQuery oraz TDataSource (znajdują się one w zakładce
Data Access palety komponentów) oraz komponent TDBGrid (zakładka Data Controls).
W komponencie TQuery należy ustawić właściwość DatabaseName na odpowiedni alias bądź ścieżkę
dostępu do katalogu, w którym znajduje się baza danych. Daje to dostęp do wszystkich tabel
umieszczonych w katalogu bazy danych. W odróżnieniu od komponentu tabeli, który pozwala na
dostęp tylko do jednej tabeli, komponent zapytania TQuery umożliwia dostęp do całej bazy, czyli
do wszystkich tabel. Oczywiście zastosowanie komponentu TTable oraz TQuery jest inne. Następnie
należy połączyć komponent TQuery ze źródłem danych TDataSource poprzez właściwość DataSet
oraz komponent TDBGrid z komponentem TDataSource poprzez właściwość DataSource. W trakcie
ćwiczenia należy modyfikować działanie komponentu TQuery poprzez ustalanie wartość właściwości
SQL, a następnie ustalać wartość właściwości Active na True.
1.2. Komenda SELECT
Komenda SELECT jest podstawową komendą języka SQL, służącą do zadawania zapytań. Jej
podstawową składnią jest:
SELECT co FROM skąd
Przykład:
SELECT firma, miasto, rczn zakup FROM klienci
Dodanie klauzuli WHERE <Wyrażenie logiczne> pozwala na umieszczenie w zapytaniu tylko tych
rekordów, dla których warunek przyjmuje wartość TRUE. Klauzula ORDER BY <wyr> powoduje zmianę
porządku wyświetlanych danych.
2
1. Kwerendy
SELECT firma, miasto, rczn_zakup FROM klienci
WHERE rczn_zakup > 1000 ORDER BY miasto, firma
Do zapytania domyślnie kierowane są wszystkie rekordy. Dodanie klauzuli DISTINCT zaraz za
słowem SELECT powoduje wykluczenie powtarzających się wierszy.
SELECT
WHERE
SELECT
WHERE
biura.nr_biura FROM biura, klienci
biura.nr_biura = klienci.nr_biura
DISTINCT biura.nr_biura FROM biura, klienci
biura.nr_biura = klienci.nr_biura
Domyślnie wszystkie kolumny wyników zapytań przyjmują nazwę pola, z którego pochodzą dane,
ale można nadać im inną nazwę. Nazwa ta jednak musi spełniać wszystkie wymogi nazw pól tabeli.
SELECT nr_klienta AS Numer, firma AS Nazwa FROM klienci
W przypadku, gdy trzeba wybrać wszystkie pola z tabeli, można ich listę zastąpić symbolem *.
SELECT klienci.*, biura.miasto AS Biuro
FROM klienci, biura
WHERE klienci.nr_biura = biura.nr_biura ORDER BY firma
Elementy wybrane w zapytaniach mogą być także funkcjami. Oto kilka funkcji, których można
używać z elementem wyboru będącym polem lub wyrażeniem zawierającym nazwy pól:
AVG(<element wyb>)
COUNT(<element wyb>)
MIN(<element wyb>)
MAX(<element wyb>)
SUM(<element wyb>)
SELECT
SELECT
SELECT
SELECT
SELECT
Uśrednianie kolumny danych numerycznych,
Zlicza elementy wyboru w kolumnie,
Wyznacza najmniejszą wartość elementu kolumny,
Wyznacza największą wartość elementu kolumny,
Sumuje kolumny danych numerycznych.
AVG(rczn_zakup) AS ŚREDNIA FROM klienci
MIN(rczn_zakup) AS MINIMUM FROM klienci
MAX(rczn_zakup) AS MAKSIMUM FROM klienci
COUNT(rczn_zakup) AS LICZBA FROM klienci
SUM(rczn_zakup) AS SUMA FROM klienci
Jeżeli tworzymy zapytanie z kilku tabel to istnieje możliwość, że nazwy pól w tych tabelach pokryją
się. W celu rozróżnienia tych pól można umieścić zaraz za nazwą pola lokalny alias, który jest aktualny
tylko w czasie wykonywania zapytania. Aliasy lokalne stosowane są również w sytuacji, gdy potrzebne
jest uproszczenie nazwy tabeli, bądź jej skrócenie w celu zwiększenia czytelności.
SELECT a.nr_klienta, a.firma, a.miasto, b.miasto AS Biuro
FROM klienci a, biura b
WHERE a.nr_biura = b.nr_biura ORDER BY a.firma
1.2. Komenda SELECT
3
Kryterium wyboru umieszczone za klauzulą WHERE można budować z wielu pojedynczych wyrażeń
logicznych używając słów OR lub AND. Można tam umieścić zarówno warunki łączenia tabel jak i
odfiltrowywania rekordów. Do budowania pojedynczych wyrażeń logicznych należy stosować
następujących operatorów:
=
równe,
<> różne,
>
większe,
<
mniejsze,
>= większe równe,
<= mniejsze równe,
a także operatorów ALL(<zapytanie wtórne>), ANY | SOME(<zapytanie wtórne>), klauzuli [NOT]
BETWEEN <minimum> AND <maksimum>, [NOT] EXIST(<zapytanie wtórne>) oraz [NOT] IN
<zbiór wartości> i [NOT] LIKE <wzorzec>. Zapytanie wtórne to polecenie SELECT wewnątrz
głównego polecenia SELECT. W klauzuli WHERE można użyć kilku zapytań wtórnych na tym samym
poziomie (nie zagnieżdżonych). W ostatniej klauzuli dopuszcza się występowanie symboli
wieloznacznych takich jak:
dowolny znak,
% sekwencja dowolnych znaków.
SELECT nr_klienta, firma, miasto, nr_biura FROM klienci
WHERE nr_biura != "4" ORDER BY firma
SELECT firma, miasto FROM klienci WHERE rczn_zakup > ALL
(SELECT rczn_zakup FROM klienci WHERE miasto = "New York")
SELECT firma, miasto FROM klienci WHERE rczn_zakup > ANY
(SELECT rczn_zakup FROM klienci WHERE miasto = "New York")
SELECT * FROM klienci WHERE rczn_zakup BETWEEN 1000 and 2000
SELECT * FROM biura WHERE NOT EXIST (SELECT * FROM klienci, biura
WHERE klienci.nr_biura = biura.nr_biura)
SELECT adres, miasto FROM biura WHERE nr_biura IN ("1","2","3")
SELECT * FROM klienci WHERE miasto LIKE ’N%’
SELECT * FROM klienci WHERE stan LIKE ’_A’
Dodanie klauzuli GROUP BY <kolumna grupowania> powoduje grupowanie wierszy w
wygenerowanym wyniku zapytania na podstawie wartości kolumny (kolumn). Pozwala to naprzykład
na podsumowanie wartości sprzedaży w filiach firmy, położonych w różnych firmach.
Użycie klauzuli HAVING <warunek filtrujacy> pozwala na określenie warunku filtrującego, który
muszą spełniać grupy, aby zostały włączone do wyników kwerendy. Klauzula HAVING powinna zostać
użyta z klauzulą GROUP BY. Może ona zostać użyta z dowolną liczbą warunków filtrujących,
połączonych operatorami AND i OR. Można również używać operatora NOT, zmieniającego wartość
logiczną wyrażeń na przeciwną. Parametr WarunekFiltrujący nie może zawierać kwerendy wtórnej.
W klauzuli HAVING wolno używać lokalnych aliasów i funkcji pól. W wypadku, gdy klauzula HAVING
nie zawiera funkcji pól, należy używać klauzuli WHERE, z uwagi na większą szybkość wykonania.
4
1. Kwerendy
SELECT firma, miasto, rczn_zakup, nr_biura FROM klienci ORDER BY
firma GROUP BY miasto HAVING nr_biura > "2"
Klauzula UNION [ALL] <polecenie select> powoduje połączenie wyników zapytania z wynikiem
innego polecenia zapytania. Standardowo klauzula ta sprawdza połączone wyniki i eliminuje
powtarzające się wiersze. Dodanie klauzuli ALL spowoduje pominięcie tej eliminacji.
SELECT * FROM klienci WHERE nr_biura = "2" UNION
SELECT * FROM klienci WHERE nr_biura = "4"
Klauzula ORDER BY <elementy porządkujące> uporządkowuje wyniki zapytania. Standardowo
wyniki zapytania wyświetlane są w kolejności rosnącej. Dodanie klauzuli DESC umożliwia sortowanie
w kolejności malejącej.
SELECT klienci.firma, klienci.miasto, biura.miasto FROM klienci, biura
WHERE klienci.nr_biura = biura.nr_biura
ORDER BY biura.miasto, klienci.firma DESC
Istnieje możliwość utworzenia sparametryzowanych zapytań (np. w kryterium wyboru). W tym
celu należy, przed uruchomieniem kwerendy, określić wartość parametru Params. Należy wykonać to
programowo, umieszczając przed wykonaniem zapytania kod programu
Procedure TForm1.Button1Click(Sender: TObject);
begin
With Query1 Do
begin
Close;
Unprepare;
Try
ParamByName(’MIASTO’).AsString := Edit1.Text;
Prepare;
Open;
Except
On EDBEngineError Do
ShowMessage(’Bledna skladnia zapytania SQL.’);
On EDatabaseError Do
ShowMessage(’Bledny parametr lub zapytanie.’)
end
end
end;
W powyższym przypadku komenda zapytania może mieć następującą postać:
SELECT * FROM klienci WHERE UPPER(miasto) = UPPER(:MIASTO)
1.3. „Żywe” kwerendy
Domyślnie wynik wykonania zapytania jest zbiorem danych tylko do odczytu. Zbiór danych, który
otrzymuje się z zapytania, można wyświetlać w obiektach kontrolnych, lecz użytkownicy nie mogą
1.3. „Żywe” kwerendy
5
tych danych edytować. Aby umożliwić edycję danych zapytania, należy sprawić, aby zwrócony zbiór
danych był „żywy” — możliwy do edycji.
Można żądać, aby zapytanie zwróciło „żywy” zbiór danych. Umożliwia to właściwość RequestLive
komponentu TQuery. Aby zbiór danych zwrócony przez zapytanie mógł być edytowany, przez
użytkownika, należy ją ustawić na wartość True. Niestety nie zawsze ma się gwarancję na to,
że zwrócony zbiór danych będzie edytowalny. Jednak kiedy tylko to możliwe, system BDE usiłuje
spełniać oczekiwania projektanta. Istnieją pewne ograniczenia, które decydują o tym, czy wynik
zapytania będzie można edytować. Głównie zależy to od tego, czy zapytanie jest przetwarzane przez
system BDE, czy też przez narzędzia serwera baz danych. Niejednorodne złączenia oraz zapytania
realizowane w bazach lokalnych, takich jak np. Paradox, są wykonywane przez BDE. Zapytania
dotyczące oddalonej bazy danych serwera SQL są analizowane przez sam serwer.
To, czy zbiór danych będący wynikiem zapytania może być edytowany, określa właściwość
CanModify, która w przypadku gdy możliwa jest edycja zapytania, zwraca wartość True.
Jeśli projektant żąda, aby wynik zapytania mógł być edytowany, ale składnia wyrażenia SELECT
nie pozwala na to, BDE zwróci:
❏ wynik tylko do odczytu w przypadku zapytań wykonywanych na bazach lokalnych typu Paradox
lub dBASE.
❏ kod błędu w przypadku zapytań wykonywanych na oddalonym serwerze SQL.
1.3.1. Wymagania i ograniczenia dla „żywych” wyników zapytania
W przypadku zapytań, które używają lokalnego SQL, BDE oferuje rozszerzone wsparcie
edytowalnych, żywych wyników zapytań zarówno opartych na jednej, jak i wielu tabelach. Local SQL
jest używany, kiedy zapytanie jest wykonywane dla jednej lub więcej tabel lokalnych typu Paradox
lub dBase, albo dla jednej lub wiecej tabel zdalnego serwera, kiedy nazwy tych tabel w zapytaniu są
poprzedzone nazwą aliasu bazy danych.
Żywy wynik zapytania wykonanego na pojedynczej tabeli lub widoku jest zwracany, gdy zapytanie
to nie zawiera następujących elementów:
❏
❏
❏
❏
❏
❏
klauzuli DISTINCT w wyrażeniu SELECT,
złąceń typu INNER, OUTER lub UNION,
funkcji agregujących, z klauzulą lub bez klauzuli GROUP BY lub HAVING,
podzapytań,
klauzul ORDER BY nie bazujących na indeksie
gdy zapytanie bazuje na tabelach lub widokach, które nie dają się aktualizować
W przypadku zapytań wykonywanych na oddalonym serwerze SQL, które zawierają wszystkie
zapytania wykonane wyłącznie na zdalnym serwerze bazy danych, żywy wynik zapytania jest
okraniczony do standardu zdefiniowanego przez SQL-92 oraz przez dodatkowe ograniczenia narzucone
przez rodzaj serwera.
W tym przypadku, żywy wynik zapytania wykonanego na pojedynczej tabeli lub widoku jest
zwracany, gdy zapytanie to nie zawiera następujących elemetnów:
❏
❏
❏
❏
klauzuli DISTINCT w wyrażeniu SELECT,
funcji agregujących z klauzulą lub bez klauzuli GROUP BY lub HAVING,
odwołań do więcej niż jednej tabeli bazowej lub widoków, które mogą być uaktualniane,
podzapytań, które odwołują się do tabeli w klauzuli FROM lub innych tabel.
1.3.2. Aktualizacja wyników zapytania tylko do odczytu
Aplikacja może aktualizować dane zwrócone w zbiorze tylko do odczytu, jeżeli zastosowano tryb
buforowania zmian. W celu zaktualizowania zbioru danych tylko do odczytu, należy:
6
1. Kwerendy
❏ dodać komponent TUpdateSQL do modułu danych lub formularza, który daje mołiwość aktualizacji
takiego wyniku zapytania,
❏ wprowadzic aktualizujące wyrażenie SQL dla właściwości ModifySQL, InsertSQL lub DeleteSQL,
❏ dla komponentu TQuery ustawić właściwość CachedUpdate na wartość True.
Download