Oracle 10g i Delphi 7. Programowanie baz danych
Artur
Oracle 10g to kolejna wersja chyba najbardziej znanej bazy danych. Jej stabilność i wydajność to już niemal legenda. W oparciu o Oracle tworzone są setki aplikacji bazodanowych operujących na milionach rekordów. Tego typu aplikacje często muszą być przygotowane w krótkim czasie. Do takich właśnie zastosowań doskonale nadaje się Delphi -- środowisko programistyczne umożliwiające szybkie tworzenie aplikacji. Dzięki zaangażowaniu firm trzecich powstały komponenty, moduły i biblioteki pozwalające na współpracę Oracle i Delphi oraz sprawne budowanie aplikacji bazodanowych łączących te platformy.
1 ORACLE 10g
2 BDE
2.1 Parę słów o BDE
2.2 Tworzenie połączenia z bazą danych
2.3 <b><b><b><b>Komponent Table</b></b></b></b>
2.4 <b><b><b><b><b><b>Specjalne cechy komponentu Table</b></b></b></b></b></b>
2.5 <b><b><b><b><b><b>Metoda Locate</b></b></b></b></b></b>
2.6 <b><b><b><b><b><b>Podsumowanie BDE</b></b></b></b></b></b>
3 <b><b><b><b><b><b>ADO</b></b></b></b></b></b>
3.7 <b><b><b><b><b><b>Wstęp do ADO</b></b></b></b></b></b>
3.8 <b><b><b><b><b><b>ADOConnection i łączenie z bazą</b></b></b></b></b></b>
3.9 <b><b><b><b><b><b>Pliki DataLink i przenośność aplikacji ADO</b></b></b></b></b></b>
3.10 <b><b><b><b><b><b>Przykładowa aplikacja ADO</b></b></b></b></b></b>
3.11 <b><b><b><b><b><b>Zapytania z parametrami</b></b></b></b></b></b>
3.12 <b><b><b><b><b><b>Podsumowanie technologii ADO</b></b></b></b></b></b>
4 <b><b><b><b><b><b>dbExpress</b></b></b></b></b></b>
4.13 <b><b><b><b><b><b>Parę słów o dbExpress</b></b></b></b></b></b>
4.14 <b><b><b><b><b><b>Nawiązywanie połączenia z bazą danych</b></b></b></b></b></b>
4.15 <b><b><b><b><b><b>SQLQuery i wyświetlanie danych</b></b></b></b></b></b>
4.16 <b><b><b><b><b><b>Edycja danych</b></b></b></b></b></b>
4.17 <b><b><b><b><b><b>Podsumowanie dbExpress</b></b></b></b></b></b>
5 <b><b><b><b><b><b>ODAC</b></b></b></b></b></b>
5.18 <b><b><b><b><b><b>Wstęp</b></b></b></b></b></b>
5.19 <b><b><b><b><b><b>Instalacja</b></b></b></b></b></b>
5.20 <b><b><b><b><b><b>Paleta komponentów ODAC</b></b></b></b></b></b>
5.21 <b><b><b><b><b><b>Tworzenie połączenia z bazą danych</b></b></b></b></b></b>
5.22 <b><b><b><b><b><b>OraSQL</b></b></b></b></b></b>
5.23 <b><b><b><b><b><b>Podsumowanie ODAC</b></b></b></b></b></b>
6 <b><b><b><b><b><b>Tworzenie niestandardowej siatki</b></b></b></b></b></b>
6.24 <b><b><b><b><b><b>Dopasowanie szerokości kolumn</b></b></b></b></b></b>
7 <b><b><b><b><b><b>Raportowanie bazy danych Oracle</b></b></b></b></b></b>
7.25 <b><b><b><b><b><b>Rave Reports - raportowanie za pomocą kodu</b></b></b></b></b></b>
8 <b><b><b><b><b><b>Podsumowanie</b></b></b></b></b></b>
Mnóstwo informacji na temat Oracle 10g, programowania tej bazy danych w Delphi i raportowaniu za pomocą Rave Reports znajdziecie w książce "Oracle 10g i Delphi. Programowanie baz danych", której autorami są Artur Mościcki i Igor Kruk.
Więcej informacji o ksiażce znajdziecie na stronie
http://helion.pl/ksiazki/oradel.htm
ORACLE 10g
Nie będę tu przedstawiał zagadnień związanych z instalacją i konfiguracją Oracle 10g (znajdziecie to w książce), a poza tym, w przypadku Oracle 10g, nie jest to proces bardzo skomplikowany. Skupię się tylko na przedstawieniu dlaczego warto poznawać Oracle oraz przedstawię podstawy pracy.
Oracle 10g to system baz danych z wyższej półki, za którym stoi potężna korporacja zrzeszająca dziesiątki tysięcy wykwalifikowanych pracowników i programistów, ciągle ulepszających swój produkt. Oracle 10g wyróżniają następujące cechy:
- wydajność bazy,
- dostępność na każdą platformę,
- przenośność (migracje),
- skalowalność,
- zautomatyzowanie czynności stricte administracyjnych,
- proste użytkowanie,
- obszerna dokumentacja dostępna na stronie producenta,
- silne wsparcie ze strony producenta i użytkowników (mnóstwo serwisów internetowych poświęconych Oracle i Oracle 10g),
- dostępność partycjonowania, indeksu bitmapowego,
- szereg dodatków, np. pakiet Oracle 10g Companion,
- zaangażowanie się firm trzecich w tworzenie komponentów, modułów, bibliotek pozwalających na współpracę Oracle i różnych środowisk programowania, np. Delphi,
- automatyczne monitorowanie i diagnostyka pracy serwera bazy danych ? mechanizm autodiagnozowania ADDM (Automatic Database Diagnostic Monitor), monitorujący w regularnych odstępach wydajność bazy i w razie potrzeby analizujący przyczyny problemu i sugerujący przeciwdziałanie,
- narzędzia doradcze (SQL Tuning Advisor i SQL Access Advisor), tworzące zalecenia dla optymalizacji wykonywania zapytań SQL,
- wysokie bezpieczeństwo danych.
Dodatkowym atutem przemawiającym za poznaniem i przetestowaniem serwera baz danych Oracle 10g jest fakt, iż ponad 80% dużych komercyjnych witryn w Internecie działa właśnie w oparciu o Oracle.
Jeszcze słowo o wymaganiach:
- minimum 256 MB pamięci operacyjnej,
- ilość pamięci wirtualnej dwukrotnie większa od ilość RAM-u,
- minimum 100 MB wolnego miejsca w katalogu tymczasowym,
- 1,5 GB przestrzeni dyskowej dla binariów i przykładowej bazy,
- procesor co najmniej 200 MHz.
Oczywiście dobrze jest mieć lepsze parametry - u mnie na komputerze (384MB RAMu i procesor 800 MHz) Oracle działa bez problemów. Oczywiście należy pamiętać o tym że tuż po włączeniu kompa, Oracle nie będzie działał od razu - musi się najpierw wszystko pouruchamiać - a to trwa do kilku minut (na gorszych sprzętach).
Ok, znamy już zalety i wymagania Oracle - to teraz przedstawię najwiażniejsze podstawy pracy z Oracle 10g.
Najważniejszymi narzędziami w Oracle 10g są Enterprise Manager (do zarządzania Oraclem) i iSQL *Plus (do wykonywania instrukcji SQL, PL/SQL, pakietów itp) - oba narzędzia dostępne są z poziomu przeglądarki internetowej, co jest niewątpliwym plusem.
Aby uruchomić Enterprise Managera należy w oknie przeglądarki wpisać http://localhost:5500/em następnie podać login i hasło użytkownika (np. takie jak podczas instalacji Oracle) i można już administrować Oracle 10g - oczywiscie nie przesadzajcie z dłubaniem w oracle - bo można go uszkodzić :)
Natomiast żeby odpalić iSQL *Plusa trzeba w oknie przeglądarki wpisać http://localhost:5560/isqlplus i znów podać login i hasło.
Oki, aby można było przetestować działanie przedstawionych w dalszej części artykułu programów proponuję stworzyć nowego użytkownika, nadać mu wszystkie możliwe uprawnienia i role i dodać do grupy administratorów (nie będę opisywał szczegółówo, jak się to robi - powiem tylko że można to zrobić w Enterprise Managerze - po szczegółowe informacje odsyłam do dokumentacji Oracle lub do książki). Nie jest to takie trudne - jak otworzysz Enterprise managera to od razu zobaczysz odpowiednie linki. oczywiście wszystkie role i uprawnienia nie są konieczne do tego by zaprezentowane przykłady zadziałały, ale dzięki temu stworzymy administratora Oracle, który będzie mógł zrobić praktycznie wszystko w racle, więc wcześniej czy później w pracy z Oracle zetkniesz się z tym zagadnieniem. Użytkownika tego (jego loginu i hasła) proponuję używać również w dalszej części tego artykułu.
No i zostało nam jeszcze stworzenie przykładowych tabel w Oracle. Powiedzmy, że będą to tabele przechowujące informacje o książkach. Uruchom iSQL Plusa i wpisz poniższe polecenia w celu utworzenia tabel
CREATE TABLE Autorzy
(
id_autora NUMBER(10) PRIMARY KEY,
imie VARCHAR2(20) NOT NULL,
nazwisko VARCHAR2(30) NOT NULL
);
CREATE TABLE Kategorie
(
id_kategorii NUMBER(10) PRIMARY KEY,
nazwa VARCHAR2(30) NOT NULL
);
CREATE TABLE Ksiazki
(
ISBN VARCHAR2(50) PRIMARY KEY,
tytul VARCHAR2(100) NOT NULL,
podtytul VARCHAR2(100),
liczba_stron NUMBER(10),
id_kategorii NUMBER(10) REFERENCES Kategorie(id_kategorii),
recenzja VARCHAR2(1000)
);
CREATE TABLE Autorzy_Ksiazki
(
id_autora_ksiazki NUMBER(10) PRIMARY KEY,
id_autora NUMBER(10) REFERENCES Autorzy(id_autora),
ISBN VARCHAR2(50) REFERENCES Ksiazki(ISBN)
);
Relacje pomiędzy tabelami widać praktycznie od razu, więc nie będę dokumentował ich rysunkiem.
Ok, to tyle jeśli chodzi o Oracle - wiem ze mało, ale czas przejść do dalszej części, czyli do technologii dostępu do baz danych. Dużo więcej informacji na temat Oracle 10g i pracy w nim, oraz o tworzeniu interfejsow WWW w czystym PL/SQL (bez użycia Delphi czy innego środowiska) znajdziecie w pierwszej części książki "Oracle 10g i Delphi. Prgramowanie baz danych".
BDE
Parę słów o BDE
BDE (Borland DataBase Enigme) to technologia, która została stworzona jako alternatywa dla technologii ODBC (tej już nie będę omawiał w tym artykule). Powstała przy współpracy kilku firm, m.in. Borland i Oracle. Kiedyś była to podstawowa technologia dostępu do baz danych, obecnie jest wypierana przez inne, takie jak ADO czy dbExpress. Zaletą BDE jest większa w porównaniu z ODBC szybkość działania oraz prostota obsługi, wadą zaś ? przenośność. Wynika to z tego, że BDE nie obsługuje systemu zarządzania baz danych bezpośrednio, lecz robi to poprzez pośrednika, jakim jest program SQL Links. Obecnie Borland rezygnuje z rozwijania tej technologii, niemniej można ją wykorzystać nawet do łączenia się z bazami danych stworzonymi w Oracle 10g. Przyjrzyjmy się palecie komponentów BDE dostępnych w Delphi 7.
Na zakładce BDE znajduje się parę komponentów
- Table ? umożliwia pracę z tabelami bazy danych;
- Query ? umożliwia wykonywanie zapytań SQL;
- StoredProc ? umożliwia wykonywanie procedur składowanych na serwerze baz danych;
- Database ? umożliwia zdefiniowanie połączenia z bazą danych;
- Session ? służy do globalnej kontroli komponentów Database. Domyślnie tworzony jest automatycznie (właściwość SessionName komponentu Database ustawiana jest na Default). Jeśli jednak użytkownik tworzy aplikacje wielowątkową, to powinien dla każdego wątku używać oddzielnego komponentu;
- BatchMove ? służy do kopiowania zbioru danych. Może być używany do konwersji tabel na różne formaty baz danych lub do tworzenia zbioru rekordów odłączonych;
- UpdateSQL ? pozwala na wykonywanie instrukcji SQL (UPDATE). Buforuje zbiór danych;
- NestedTable ? umożliwia hermetyzowanie zbioru danych zagnieżdżonego w innej tabeli.
Tworzenie połączenia z bazą danych
Aby stworzyć nowe połączenie z bazą danych wykorzystujące technologię BDE, należy użyć programu BDE Administrator. Program ten można uruchomić poza Delphi 7 poprzez Start/Programy/Delphi 7/BDE Administrator. Ukaże się wówczas okno programu (rysunek poniżej), na którym będą widoczne dwie zakładki DataBase i Configuration. Na zakładce Configuration można zobaczyć, jakie sterowniki SQL Links (gałąź Drivers/Native) i ODBC (gałąź Drivers/ODBC) są dostępne
Przejdź na zakładkę Database i wybierz z menu głównego Object/New. Pojawi się nowe okienko New Database Alias (rysunek poniżej).
W oknie tym wybierz sterownik do Oracle i kliknij przycisk OK. Pojawi się ponownie okno BDE Administrator, w którym do zakładki Database dodana zostanie nowa pozycja ORACLE1. Zmień jej nazwę na ORACLEBDE (rysunek poniżej).
Aby stworzyć nowy sterownik BDE, musisz jeszcze zmienić dwie właściwości znajdujące się po prawej stronie okna w BDE Administratorze:
- w polu Server Name wpisz orcl;
- w polu User Name wpisz nazwę użytkownika bazy danych.
Na koniec naciśnij przycisk Apply (niebieska strzałka) w celu zapisania nowego połączenia BDE.
Przetestujmy teraz stworzone przed chwilą połączenia BDE.
- Otwórz Delphi i dodaj do formularza komponent Database1 z palety BDE.
- Ustaw właściwość AliasName komponentu Database1 na stworzone przed momentem połączenie ORACLEBDE.
- We właściwości DatabaseName komponentu Database1 wpisz nazwę bazy danych orcl.
- Zmień właściwość Connected komponentu Database1 na True. Pojawi się okno, w którym będziesz musiał podać hasło dostępu do bazy danych. Jeśli je podasz i właściwość Connected zostanie zmieniona na True, oznacza to, że połączenie się powiodło
Przyjrzyjmy się jeszcze właściwościom i zdarzeniom komponentu Database (tabele poniżej)
Tabela 1. Właściwości komponentu Database
Właściwość |
Tabela 2. Zdarzenia komponentu Database </td></tr> Zdarzenie</td>Opis</td></tr> </td></tr> AfterConnect</td>Zdarzenie obsługiwane po połączeniu się aplikacji z bazą danych.</td></tr> AfterDisconnect</td>Zdarzenie obsługiwane po rozłączeniu się z bazą danych.</td></tr> BeforeConnect</td>Zdarzenie obsługiwane tuż przed połączeniem się aplikacji z bazą danych.</td></tr> BeforeDisconnect</td>Zdarzenie obsługiwane tuż przed rozłączeniem się aplikacji z bazą danych.</td></tr> OnLogin</td>Zdarzenie obsługiwane w momencie podłączania się do bazy danych. W parametrze LoginParams przekazywane są nazwa użytkownika (user_name) i hasło (password), pobrane z właściwości Params komponentu. W zdarzeniu tym można umieścić obsługę własnego okna logowania (wtedy właściwość LoginPrompt musi być ustawiona na True).</td></tr> </td></tr> </table>
Komponent Table
Najprostszym sposobem dostępu do danych przechowywanych w bazie danych orcl jest użycie komponentu Table. Komponent ten oznacza po prostu tabelę bazy danych. Przyjrzyjmy się najpierw właściwościom udostępnianym przez komponent (tabela ponizej). Zdarzenia komponentu Table są bardzo podobne do udostępnianych przez komponent Query i zostały omówione w jednym z następnych podrozdziałów książki i nie chce mi się ich tu przepisywać :)
Tabela 3. Właściwści komponentu Table
Ok, zastosujmy w końcu komponent Table w praktyce. Napiszmy program, który wyświetli dane z tabeli Kategorie oraz pozwoli na ich modyfikację.
Umieść na formularzu komponenty Database1, Table1 z palety BDE, DataSource1 z karty Data Access i DBGrid1 z karty Data Control. Ustaw właściwość AliasName komponentu Database1 na stworzone przed momentem połączenie ORACLEBDE. We właściwości DatabaseName komponentu Database1 wpisz nazwę bazy danych orcl. Kliknij dwa razy właściwość Params i w oknie Value List Editor (rysunek poniżej) wpisz dwa parametry: USER NAME i PASSWORD oraz odpowiadające im wartości (nazwę użytkownika i hasło). Parametry te będą potrzebne po to, by podczas próby łączenia się z bazą danych program nie pytał o login i hasło użytkownika.Zmień właściwość LoginPrompt komponentu Database1 na False. Od tego momentu nie będzie pojawiało się okno z prośbą o podanie loginu i hasła. Zmień właściwość Connected komponentu Database1 na True. Ustaw właściwość DatabaseName komponentu Table1 na orcl. Ustaw właściwość TableName komponentu Table1 na tabelę Kategorie. Ustaw właściwość DataSet komponentu DataSource1 na Table1. Ustaw właściwość DataSource komponentu DBGrid1 na DataSource1. Dwa ostatnie kroki wykonuje się w celu wyświetlenia danych pobranych z bazy danych na komponencie DBGrid1. Na koniec zmień właściwość Active komponentu Table1 na True. Od tego momentu w komponencie DBGrid1 wyświetlone będą dane z tabeli Kategorie. Możesz zapisać i uruchomić projekt (rysunek poniżej). </ol>
OK, program wyświetla dane. Ale jak dodać nowe wpisy lub modyfikować istniejące? Żeby zmodyfikować wpis, wystarczy ustawić kursor w odpowiednim polu siatki (po prostu kliknij myszą interesujące Cię pole) i poprawić istniejący tam wpis. Natomiast żeby dodać nowy wpis, trzeba ustawić kursor w dowolnym miejscu, a następnie za pomocą klawiszy strzałek przejść na koniec tabeli. Gdy pojawią się puste pola, należy wpisać w nie nowe wartości. Oczywiście w kolumnie Id_kategorii nie można wpisywać wartości, które już istnieją, ponieważ atrybut Id_kategorii jest kluczem głównym tabeli Kategorie i jego wartości muszą być niepowtarzalne. W kolumnie Id_kategorii można wpisywać tylko wartości numeryczne. W przeciwnym wypadku program zwróci komunikat o błędzie. W następnych podrozdziałach napiszemy, jak stworzyć program, w którym użytkownik nie będzie mógł ingerować w wartości atrybutu będącego kluczem głównym tabeli.
Specjalne cechy komponentu Table
Komponent Table posiada specjalne cechy, których nie mają inne komponenty zbioru danych, np. Query. Otóż w komponencie tym dostępne są specjalne metody wyszukiwania, takie jak: FindKey, FindNearest, GotoKey, GotoNearest. My przyjrzymy się bliżej dwóm pierwszym metodom. Odpowiedzialne są one za wyszukiwanie przybliżonych wartości (FindNearest) oraz za wyszukiwanie dokładne (FindKey). Metody te wyszukują tylko po atrybutach będących indeksami lokalnymi. Natomiast indeksy lokalne można założyć tylko na atrybutach będących kluczem głównym tabeli.
Zmodyfikujmy przykład z poprzedniego podrozdziału tak, aby można było wyszukiwać książki na podstawie ISBN.
procedure TForm1.Button1Click(Sender: TObject);
begin
Table1.FindNearest([Edit1.Text]);//wyszukaj książki o podobnym ISBN
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//wyszukaj książki o identycznym ISBN, a jeśli takich nie ma, to wyświetl komunikat
if Table1.FindKey([Edit2.Text])=false then
showmessage('Książka o takim ISBN nie istnieje w bazie danych');
end;
Parametrami obu metod są tablice stałych. Każdy element tablicy odpowiada indeksowanemu atrybutowi. W przykładzie jest jeden indeks na atrybucie ISBN, dlatego wyszukiwanie odbywa się tylko po tym jednym atrybucie.
Rysunek poniżej pokazuje program podczas działania. Po wpisaniu w polach edycyjnych wartości takich, jak na rysunku, wskaźnik (czarny trójkąt) zostanie ustawiony na drugim rekordzie. Widać, że metoda FindNearest znajduje odpowiedni rekord, pomimo iż wartość ISBN różni się dwoma cyframi.
Metoda Locate
Metody FindKey i FindNearest szukały rekordy tylko po atrybucie, który był indeksem. Metoda Locate pozwala wyszukiwać rekordy według dowolnego atrybutu tabeli. Posiada ona trzy parametry:
pierwszym jest nazwa lub nazwy atrybutów, według których będzie prowadzone wyszukiwanie; drugim jest tablica wartości poszukiwanych; trzecim są opcje metody Locate. Dostępne są dwie opcje: loCaseInsensitive ? atrybuty i wartości poszukiwane są porównywane bez uwzględnienia wielkości liter, loPartialKey ? jeśli podane parametry wyszukiwania spełniają przynajmniej w części wartości występujące w polach, to metoda zwraca wartość True. </ul> </ul>Metoda Locate jako rezultat zwraca wartość typu Boolean. Jeśli znaleziony został rekord odpowiadający poszukiwanej wartości, to wynikiem działania metody jest wartość True. Zaprezentujmy wykorzystanie metody Locate na przykładzie.
Wykorzystaj przykład z podrozdziału ?Table?. Zmień właściwość TableName komponentu Table1 tak, aby wskazywała na tabelę Ksiazki. Zmień właściwość Active komponentu Table1 na True w celu wyświetlenia wszystkich rekordów. Dodaj do formularza komponenty Edit1 i Button1. W kontrolce Edit1 będziemy wpisywać tytuł poszukiwanej książki. Zmień właściwość Caption komponentu Button1 na Szukaj książek o tytule. Oprogramuj zdarzenie onClick komponentu Button1. </ol>procedure TForm1.Button1Click(Sender: TObject);
begin
//jeśli wpisano tytuł w kontrolce Edit1
if Edit1.text<>'' then
//spróbuj znaleźć książkę o podanym tytule
if Table1.Locate('Tytul',VarArrayOf([Edit1.Text]),[loPartialKey])=False
then
//jeśli nie znaleziono książki o podanym tytule, to wyświetl komunikat
showmessage('Nie znaleziono książki zawierającej taki tytuł');
end;
Jeśli chcesz wyszukiwać rekordy według dwóch atrybutów, to musisz nieco zmodyfikować parametry metody Locate:
Table1.Locate('Tytul;ISBN',VarArrayOf([Edit1.Text,Edit2.Text]),[loPartialKey]);
Podsumowanie BDE
To tyle jesli chodzi o zagadnienia związane ze starą już i powoli odchodzącą do lamusa, lecz ciągle pozwalającą na efektywne proramowanie baz danych technologią - BDE. Dużo więcej informacji znajdziecie w książce.
ADO
Wstęp do ADO
ADO (ActiveX Data Objects) jest kolejną technologią dostępu do baz danych, za pomocą której możemy programować bazę danych Oracle 10g. Wyodrębniła się ona z technologii OLE.DB i obecnie jest częścią MDAC (Microsoft Data Access Components). Więcej informacji na temat MDAC, OLE.DB i ADO znajdziecie na stronie internetowej Microsoftu www.microsoft.com.
W Delphi 7 znajduje się paleta komponentów nazwana ADO. Składa się ona z 6 komponentów:
ADOConnection i łączenie z bazą
Komponent ADOConnection jest używany do osiągnięcia wielu celów m.in. do:
realizowania wspólnego połączenie z bazą danych, dostosowania procedury logowania, sterowania transakcjami, wykonywania poleceń, redukowania liczby połączeń w aplikacji. </ul>Jako pierwsza cecha tego komponentu została wymieniona realizacja połączenia z bazą danych. Jednak komponent ten nie posiada właściwości DatabaseName ani AliasName, proces nawiązywania połączenia wyglada inaczej niż w przypadku technologii BDE:
Tworzymy nowy projekt i umieszczamy na formularzu komponent ADOConnection1. Definiujemy łańcuch połączenia ConnectionString. Możemy to zrobić na dwa sposoby: poprzez dwukrotne kliknięcie komponentu ADOConnection1, poprzez dwukrotne kliknięcie właściwości ConnectionString komponentu ADOConnection1 w Inspektorze Obiektów </ul>
Domyślnie zaznaczona jest opcja Use Connection String. Drugą możliwością definiowania łańcucha połączeń jest wskazanie pliku DataLink (opcja Use Data Link File) - zostanie ona omówiona w dalszej części artykułu.
Po kliknięciu przycisku Build pojawi się okno Właściwości łącza danych zawierające cztery zakładki: Dostawca, Połączenie, Zaawansowane, Wszystkie.Na zakładce Dostawca wybierz sterownik Oracle Provider for OLE DB. Wciskając przycisk Dalej przecjdź do następnej zakładki. Na zakładce Połączenie zdefiniuj: źródło danych ? SID (unikalny identyfikator bazy danych Oracle). Został on wybrany podczas instalacji bazy danych Oracle 10g. W moim przypadku (standardowa instalacja) jest to orcl, nazwę użytkownika bazy danych - czyli ja wpisałem artur, hasło dostępu do bazy danych dla tego użytkownika - u mnie też artur; dodatkowo można zaznaczyć dwie opcje: Puste hasło (w przypadku gdy użytkownik bazy danych nie ma zdefiniowanego hasła w bazie danych), Zezwalaj na zapisywanie hasła (jeśli nie chcemy podawać hasła przy każdej próbie połączenia z bazą danych Oracle 10g, opcja ta musi być zaznaczona). </ul>
Aby sprawdzić poprawność konfiguracji, wciśnij przycisk Testuj połączenie. W przypadku poprawnej konfiguracji otrzymasz komunikat Połączenie testowe powiodło się. Zapisz łańcuch połączeń, klikając przycisk OK na dwóch kolejnych oknach </ol>
Pliki DataLink i przenośność aplikacji ADO
Przedstawione przed chwilą zastosowanie łańcucha połączeń (ConnectionString) jest prostą metodą łączenia się z bazą danych. Posiada jednak wadę. Łańcuch połączeń jest wkompilowywany w plik exe aplikacji. Wymusza to statyczną lokalizację bazy danych. W przypadku zmiany np. nazwy użytkownika lub bazy danych należy stworzyć łańcuch połączeń od nowa, a następnie ponownie skompilować całą aplikację. Rozwiązaniem tego problemu jest zastosowanie plików łączenia danych (tzw. Data Link).
Plik Data Link to rodzaj pliku konfiguracyjnego, który posiada rozszerzenie udl. Plik ten możesz przygotować w następujący sposób:
Przykładowa zawartość pliku udl:
[oledb]
; Everything after this line is an OLE DB initstring
Provider=OraOLEDB.Oracle.1;Password=artur;Persist Security Info=True;User ID=artur;Data Source=orcl
Uwaga: Ręczne wpisanie (skopiowanie) ustawień spowoduje błąd podczas próby połączenia się z bazą danych - aby plik Data Link był poprawny należy go wykonać według powyższych punktów.
Oki teraz możemy wykorzystać plik Data Link do połączenie z bazą danych, aby to zrobić należy:
Umieścić komponent ADOConnection1 na formularzu i dwukrotnie go kliknąć. W nowo otwartym oknie (znanym już dlatego nie zamieszczam rysunku) zaznaczyć opcję Use Data Link File. Kliknąć przycisk Browse i wskazać plik udl, a następnie kliknąć przycisk Otwórz. Dokonany wybór zatwierdzić przyciskiem OK. </ol>Przykładowa aplikacja ADO
Ok, wiesz już, jak połączyć się z bazą oracle 10g za pomocą ADO, to teraz napiszę aplikację pokazującą zastosowanie technologii ADO - a konkretnie wykorzystanie komponentu ADOCommand. Wybaczcie, że nie poruszę większej ilości zagadnień związanych z ADO, ale t jest tylko artykuł:) - więcej informacji jak zwykle znajdziecie w przedstawionej wyżej książce :).
Ok, zaczynamy. ADOCommand służy do wykonywania różnego rodzaju zapytań SQL
Do definiowania zapytań służy właściwość CommandText. Podwójne kliknięcie tej właściwości spowoduje otworzenie CommandText Editora ? okna, w którym można podglądać tabele i ich atrybuty, a także formułować treść zapytania SQL.
Ja napiszę prosty program, który będzie dodawał nowe wpisy do tabeli Kategorie (do bazy danych zaprojektowanej na początku artykułu). Tabela ta posiada dwa atrybuty: Id_kategorii i Nazwa (liczbę i nazwy atrybutów łatwo sprawdzić, wydając polecenie DESC NAZWA_TABELI w iSQL*Plus). Aby stworzyć aplikację, musisz wykonać kilka kroków:
procedure TForm1.Button1Click(Sender: TObject);
begin
//zapytanie Insert wstawiające dane do tabeli
ADOCommand1.CommandText:='INSERT INTO Kategorie VAlUES ('+Edit1.Text+','''+Edit2.Text+''')';
//klauzula try przechwytująca ewentualne wyjątki
try
ADOCommand1.Execute; //wykonanie polecenia INSER
except
//poinformowanie użytkownika o wyjątku
Showmessage('Wystąpił błąd. Może to być spowodowane niewypełnieniem pola Edit lub błędem związanym z kluczem głównym tabeli Kategorie');
end;
end;
W powyższym przykładzie zapytanie zostało zbudowane za pomocą łączenia łańcuchów (stringów) - istnieje inna metoda wykonywania zapytań za pomocą parametrów. Następnie tak zbudowane zapytanie jest wykonywane (ADOCommand1.Execute). Podczas wykonywania zapytania mogą wystąpić wyjątki związane z kilkoma sytuacjami: użytkownik nie wypełnił dowolnego z pól Edit, użytkownik podał nieprawidłową wartość dla pola ID. Dlatego BARDZO ŹŁĄ praktyką jest zostawianie użytkownikowi możliwości ingerowania w klucz główny tabeli. Bardzo eleganckim i efektywnym rozwiązaniem jest użycie sekwencji - dzięki temu to serwer oracle będzie się martwił, aby atrybut Id mial odpowiednią, nie powtarzającą się wartość. Ok, to zmieńmy naszą aplikację. Najpierw stwórz w Oracle sekwencję - otwórz iSQLPlusa i wykonaj kod:
create sequence klucz_glowny_tabeli_kategorie
increment by 1
start with 1
Pierwsza linia zawiera nazwę sekwencji, druga wartość o jaką sekwencja będzie zwiększana a trzecia początkową wartość sekwencji - dzięki temu pierwszy wstawiony rekord będzie miał wartość ID 1. Oczywiście należy pamiętać o tym, że jeśli w tabeli są już jakieś rekordy to wartość początkową sekwencji należy ustawić na inną (większą) wartość. Ok, teraz należy zmienić troche stworzoną aplikację.
Usuń z formularza dwa komponenty Label1 i Edit1 ? nie będą już potrzebne. Zmień kod zdarzenia onClick komponentu Button1 na poniższy </ol>procedure TForm1.Button1Click(Sender: TObject);
begin
ADOCommand1.CommandText:='INSERT INTO Kategorie VAlUES (klucz_glowny_tabeli_kategorie.nextval ,'''+Edit2.Text+''')';
try
ADOCommand1.Execute;
except
Showmessage('Wpisz nazwę kategorii');
end;
end;
Wartości klucza głównego generowane są teraz przez sekwencję. Polecenie
klucz_glowny_tabeli_kategorie.nextval
powoduje zwiększenie o 1 ostatniej wartości klucza głównego tabeli Kategorie
Zapytania z parametrami
W powyższym przykładzie zapytania INSERT tworzone były za pomocą sklejania (konkatenacji) łańcuchów tekstowych. Istnieje inna, bardziej elegancka, metoda budowania zapytań ? z użyciem parametrów.
Zbuduj interfejs użytkownika taki jak w poprzednim nie poprawionym przykładzie. Dwukrotnie kliknij właściwość Parameters komponentu ADOCommand1 ? otworzy się nowe okno Editing ADOCommand1.ParametersDodaj dwa parametry, klikając ikonę ADD New lub wciskając klawisz Insert. Nadaj nazwy parametrom ? w tym celu zaznacz parametr w oknie Editing ADOCommand1.Parameters i uzupełnij właściwość Name w Inspektorze Obiektów. Oprogramuj zdarzenie onClick komponentu Button1. </ol>
procedure TForm1.Button1Click(Sender: TObject);
begin
//odczytanie wartości parametrów
ADOCommand1.Parameters.ParamByName('ID').Value:=Edit1.Text;
ADOCommand1.Parameters.ParamByName('NAZWA').Value:=Edit2.Text;
//tworzenie zapytania
ADOCommand1.CommandText:='INSERT INTO Kategorie (ID_KATEGORII, NAZWA) VALUES (:ID, :NAZWA)';
try
ADOCommand1.Execute; //próba wykonania zapytania
Except
//wyświetl komunikat w przypadku wystąpienia błędu
Showmessage('Błąd!! ? Wpisz poprawną wartość klucza głównego lub uzupełnij nazwę kategorii');
end;
end;
Jak widać, parametry zapytania poprzedzane są znakiem dwukropka. W przypadku gdy w zapytaniu uczestniczą wszystkie atrybuty tabeli, nie ma konieczności wymieniania ich po nazwie tabeli w poleceniu INSERT (ale jest to dobrą praktyką). Konieczność wymienienia atrybutów tabeli istnieje wówczas, gdy w poleceniu INSERT nie uczestniczą wszystkie atrybuty tabeli. Oczywiście atrybutami nieuczestniczącymi w zapytaniu INSERT mogą być tylko te, które nie posiadają predykatu NOT NULL nadanego w Oracle.
Wartość parametru można ustawić za pomocą polecenia:
ADOCommand1.Parameters.ParamByName('Nazwa paramteru').Value := Wartość;
Oczywiście znów możesz zmodyfikować program, by użytkownik nie musiał wpisywać wartości ID.
Podsumowanie technologii ADO
ADO to nowoczesna (teraz jest już ADO.NET) technologia, która jest dość szybka i efektywna. Oczywiście w artykule poruszyłem tylko małą cześć zagadnień związanych z ADO. Dużo więcej znajduje się w książce "Oracle 10g i delphi. Programownaie baz danych".
dbExpress
Parę słów o dbExpress
dbExpress to stosunkowo nowa technologia dostępu do baz danych, polecana przez firmę Borland do obsługi serwerów baz danych. Za pomocą tej technologii możemy tworzyć aplikacje pracujące w środowisku Windows i Linux (oprócz dbExpress możliwość taką udostępnia jeszcze technologia ODAC, omówiona w dalszej części artykułu). dbExpress dostępna jest w Delphi i Kyliksie. Jest to szybka i elastyczna technologia - dużo szybsza niż BDE czy ODBC. Co powoduje, że technologia ta jest szybsza od innych? W dbExpress wyniki zapytań przechowywane są w kursorach jednokierunkowych. Tego typu kursory pozwalają przejść z dowolnego rekordu do następnego, ale za to nie umożliwiają powrotu do poprzedniego. Cecha ta powoduje, że nie można używać komponentów DBGrid (przynajmniej bez specjalnych sztuczek) do prezentacji danych. Jednak takie podejście sprawia, że wszystkie operacje związane z przetwarzaniem danych wykonywane są znacznie szybciej niż w innych technologiach.
Paleta komponentów dbExpress składa się z kilku kontrolek:
SQLConnection ? komponent służący do nawiązywania połączenia z bazą danych, SQLDataSet ? komponent zbioru danych, może być używany zamiast SQLQuery, SQLTable lub SQLStoredProc, SQLQuery ? komponent służący do przechowywania zbioru danych i wykonywania zapytań SQL, SQLStoredProc ? komponent służący do wykonywania procedur składowanych na serwerze baz danych, SQLTable ? komponent służący do przechowywania zbioru danych pochodzącego z jednej tabeli, SQLMonitor ? komponent służący do monitorowania komend wysyłanych pomiędzy aplikacją a serwerem Oracle 10g, SimpleDataSet ? komponent zbioru danych. </ul>Nawiązywanie połączenia z bazą danych
Żeby połączyć się z bazą danych, musisz otworzyć Delphi i na formatce umieścić komponent SQLConnection1. Następnie należy dwukrotnie kliknąć lewym klawiszem myszy ten komponent lub kliknąć prawym klawiszem myszy i z menu podręcznego wybrać opcję Edit Connection Properties. Ukaże się nowe okno.
Zeby połączyć się z oracle w polu Connection Name musisz wybrać opcję OracleConnection, a następnie uzupełnić kilka właściwości w polu Connection Settings:
DataBase ustaw na orcl jeśli taką masz nazwę bazy danych (standardowa instalacja), UserName ? tu wpisz swoją nazwę użytkownika (u mnie artur), Password ? w polu tym wpisz hasło użytkownika bazy danych (u mnie artur). </ul> Na koniec możesz przetestować połączenie z bazą danych naciskając przycisk Test Connection (czwarty od lewej strony w oknie przedstawionym na rysunku powyżej). Jeśli otrzymasz komunikat Succesfully connected, będzie to oznaczać, że połączenie z bazą danych Oracle powiodło się. Na koniec zatwierdź zmiany poprzez naciśnięcie przycisku OK.SQLQuery i wyświetlanie danych
SQLQuery to komponent będący odpowiednikiem komponentów Query i ADOQuery. Służy do wykonywania zapytań SQL i przechowywania wynikowego zbioru danych (jeśli taki istnieje). Komponent SQLQuery różni się od odpowiedników z technologii BDE i ADO jedną ważną cechą ? dane możemy przeglądać tylko do przodu. Dlatego wyświetlanie danych za pomocą technologii dbExpress jest trochę inne niż w technologiach BDE czy ADO. Napiszmy program w oparciu o komponent SQLQuery, który wyświetli dane z tabeli Kategorie.
Umieść na formularzu komponent SQLConnection1 i skonfiguruj połączenie z bazą danych oraz zmień właściwość Connected na True. Umieść na formularzu komponent SQLQuery1 i ustaw jego właściwość SQLConnection na SQLConnection1. Kliknij dwukrotnie właściwość SQL komponentu SQLQuery1 i w oknie String List Editor wpisz treść zapytania SQL, które wyświetli dane z tabeli Kategorie: ```delphi SELECT * FROM Ksiazki ``` Umieść na formularzu komponent ListView1 z palety Win32. To na nim będziemy wyświetlać dane pobrane z tabeli Kategorie. Zmień kilka właściwości komponentu ListView1, żeby przystosować go do wyświetlania danych z bazy danych: właściwość Align ustaw na alTop, żeby komponent był dopasowany do formularza, właściwość ViewStyle ustaw na vsReport, żeby móc wyświetlać dane w postaci kolumn i wierszy, właściwość ReadOnly zmień na True, żeby nie można było zmieniać danych wyświetlanych w komponencie ListView1, właściwość RowSelect ustaw na True, żeby wybrany wiersz tabeli był w całości zaznaczany, właściwość GridLines ustaw na True, żeby widoczna była siatka oddzielająca wiersze i kolumny, właściwość ShowColumnHeader ustaw na True, żeby widoczne były nagłówki kolumn. </ul> Aby dodać nagłówki kolumn, kliknij prawym klawiszem myszy komponent ListView1 i z menu podręcznego wybierz opcję Column Editor. Za pomocą przycisku Add New dodaj kolumny i zmień ich właściwość Caption według własnego uznania. Oczywiście za pomocą przycisków Move Selected Up, Move Selected Down możesz zmieniać kolejność kolumn, a za pomocą przycisku Delete Seleted ? usuwać niepotrzebne kolumny.Dodaj do formularza przycisk i zmień jego właściwość Caption na Wyświetl dane. Oprogramuj zdarzenie onClick przycisku Button1 Naciśnięcie tego przycisku będzie powodowało wyświetlenie danych pobranych z bazy. </ol>
procedure TForm1.Button1Click(Sender: TObject);
var
lista:TListItem; //zmienna, która posłuży do dodawania wierszy
begin
ListView1.Items.Clear; //wyczyść zawartość ListView1
SQLQuery1.Active:=True; //wykonaj zapytanie SQL
// dopóki są dane w zbiorze danych
while not SQLQuery1.Eof do
begin
lista:=ListView1.Items.Add; //stwórz nowy wiersz
// do wiersza wstaw wartość przechowywaną przez pole ID ...
lista.Caption:=SQLQuery1.FieldValues['ID'];
// ... a następnie wstaw wartości z kolumny nazwa
try
lista.SubItems.Add(SQLQuery1.FieldValues['NAZWA'])
except
lista.SubItems.Add('');
end;
SQLQuery1.Next; //przejdź do kolejnego rekordu zbioru danych
end;
SQLQuery1.Close; //zamknij komponent SQLQuery1
end;
Jak zapewne zauważyłeś, pierwszą kolumnę w komponencie ListView1 dodaje się poprzez wywołanie metody
Caption
natomiast następne poprzez wywołanie metody
SubItem.Add
Wypisywanie wartości pól, które mogą nie zawierać danych, powinno odbywać się w bloku
try
...
except
...
end;
tak jak to zaprezentowałem w przypadku danych z kolumny Nazwa (choć kolumna ta jest oznaczona jako Not Null - więc musi posiadać jakąś wartość - blok try ... except zastosowałem, żeby pokazać mechanizm).
Skompiluj projekt i uruchom go poza środowiskiem Delphi. Uruchamiając program z poziomu środowiska Delphi (jesli zawiera on blok try ... except), możesz otrzymać komunikat o błędzie, np. wtedy gdy jedno z pól nie będzie zawierało danych. Dzieje się tak dlatego, że Delphi wykrywa wyjątek jeszcze przed zadziałaniem bloku try ... except.
Edycja danych
Przed chwilą zaprezentowałem program, który pozwalał przeglądać dane, w tym zaś rozbuduję aplikację, by umożliwiała edycję danych: dodawanie, modyfikowanie i usuwanie rekordów. Zapytania będę budował na zasadzie sklejania łańcuchów tekstowych, jednak nic nie stoi na przeszkodzie, by zastosować parametry.
Otwórz projekt w poprzedniego podrozdziału i dodaj do niego komponent Label, pole edycyjne (Edit), trzy przyciski (Button). Komponent Label będzie wyświetlać napis "Nazwa". Pole edycyjne posłuży do dodawania nowych i aktualizacji istniejących wpisów. Za pomocą przycisków będziemy mogli dodać, zmodyfikować lub usunąć wpis. Proces dodawania rekordu będzie polegał na uzupełnieniu pola Nazwa i naciśnięciu przycisku Dodaj dane. Proces modyfikacji będzie polegał na wybraniu w komponencie ListView1 wiersza, który ma zostać zmieniony. Dane pobrane z tego wiersza zostaną wyświetlone w polu edycyjnym (Nazwa). Użytkownik będzie mógł nanieść poprawki i nacisnąć przycisk Modyfikuj dane. Po wykonaniu tych czynności dane zostaną zmodyfikowane. Proces usuwania danych będzie polegał na wskazaniu w komponencie ListView1 rekordu, który ma zostać usunięty, i wybraniu przycisku Usuń dane. Zmień właściwości przed chwilą wstawionych komponentów, tak aby stworzyć interfejs użytkownika. Stwórz zmienną globalną do zapamiętania wartości pola Id_kategorii klikniętego w Listview1. ```delphi zapamietaj_id:string; //zmienna przechowująca wartość ID_kategorii zaznaczonego wiersza ``` Procedura wyświetlajaca dane jest następująca: ```delphi procedure TForm1.Button1Click(Sender: TObject); var lista:TListItem; begin ListView1.Items.Clear; SQLQuery1.Active:=False; SQLQuery1.SQL.Clear; SQLQuery1.SQL.Add('SELECT * FROM Kategorie'); SQLQuery1.Active:=True; while not SQLQuery1.Eof do begin lista:=ListView1.Items.Add; lista.Caption:=SQLQuery1.FieldValues['ID_KATEGORII']; try lista.SubItems.Add(SQLQuery1.FieldValues['NAZWA']) except lista.SubItems.Add(''); end; SQLQuery1.Next; end; SQLQuery1.Close; end; ``` Napisz odpowiedni kod służący do wstawiania nowych rekordów do tabeli Kategorie. Oprogramuj zdarzenie onClick komponentu Button2: ```delphi procedure TForm1.Button2Click(Sender: TObject); var id,i:integer; nazwa:string; begin if (Edit1.Text<'') then begin nazwa:=''''+Edit1.Text+''''; SQLQuery1.Close; SQLQuery1.SQL.Clear; SQLQuery1.SQL.Add('INSERT INTO Kategorie VALUES (klucz_glowny_tabeli_kategorie.nextval,'+nazwa+')'); try SQLQuery1.ExecSQL; except showmessage('Wystąpil bląd podczas wstawiania rekordu. Sprawdź, czy wszystkie pola są poprawnie wypelnione') end; end; Button1Click(Sender); Edit1.Text:=''; SQLQuery1.Active:=False; end; ``` Na początku i na końcu sczytywanych wartości pól typu łańcuchowego dodajemy apostrof (czynność ta jest konieczna podczas budowania zapytań poprzez łączenie łańcuchów). Oprogramuj zdarzenie onSelectItem komponentu ListView1. Zdarzenie to zostanie wywołane w momencie zaznaczenia wiersza (kliknięcie lewym klawiszem myszy siatki ListView1) i spowoduje uzupełnienie pól edycji i zapamiętanie wartości ID_kategorii. Czynność ta będzie przydatna przy modyfikacji i usuwaniu rekordów z bazy danych. ```delphi procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean); var i:integer; begin zapamietaj_id:=''''+Item.Caption+''''; Edit1.Text:=Item.SubItems.Strings[0]; end;procedure TForm1.Button4Click(Sender: TObject);
begin
if zapamietaj_id<>'' then
begin
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('DELETE FROM Kategorie WHERE ID_KATEGORII='+zapamietaj_id);
SQLQuery1.ExecSQL;
end
else
showmessage('Zaznacz rekord, który chcesz usunąc');
Button1Click(Sender);
zapamietaj_id:='';
Edit1.Text:='';
end;
Odczytywanie wartości pierwszej kolumny wykonuje się za pomocą instrukcji
```delphi
Item.Caption
natomiast odczytywanie wartości pozostałych kolumn jest możliwe poprzez wykonanie instrukcji
Item.SubItems.Strings[numer]
Numeracja jest oczywiście od zera. Tak więc, żeby odczytywać wartość pola z drugiej kolumny, należy posłużyć się instrukcją
Item.SubItems.Strings[0].
Kolejną czynnością jest oprogramowanie zdarzenia onClick komponentu Button3. W zdarzeniu tym będziemy zapisywać do bazy danych dokonane przez użytkownika zmiany, czyli będziemy wykonywać instrukcję UPDATE. Oczywiście użytkownik przed dokonaniem modyfikacji będzie musiał kliknąć wiersz, którego dane chce zmienić, czyli wykonana zostanie procedura przedstawiona w poprzednim punkcie Procedura modyfikacji danych niewiele różni się od procedury wstawiającej rekord do bazy danych, więc nie będę jej omawiał.
```delphi
procedure TForm1.Button3Click(Sender: TObject);
var id,i:integer;
nazwa:string;
begin
if (zapamietaj_id<'') then
if (Edit1.Text<'') then
begin
nazwa:=''''+Edit1.Text+'''';
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('UPDATE Kategorie SET NAZWA='+nazwa+' WHERE ID_KATEGORII='+zapamietaj_id);
try
SQLQuery1.ExecSQL;
except
showmessage('Wystąpil bląd podczas aktualizacji rekordu. Sprawdź, czy wszystkie pola są poprawnie wypelnione')
end;
end
else
showmessage('Pole Nazwa musi byc uzupelnione')
else
showmessage('Zaznacz wpis, który chcesz zmienic');
Button1Click(Sender);
zapamietaj_id:='';
Edit1.Text:='';
end;
```
Na koniec pozostało nam oprogramowanie zdarzenia onClick komponentu Button4. Kliknięcie tego przycisku będzie powodowało usunięcie wskazanego w siatce ListView1 rekordu.
```delphi
procedure TForm1.Button4Click(Sender: TObject);
begin
if zapamietaj_id<'' then
begin
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('DELETE FROM Kategorie WHERE ID_KATEGORII='+zapamietaj_id);
SQLQuery1.ExecSQL;
end
else
showmessage('Zaznacz rekord, który chcesz usunąc');
Button1Click(Sender);
zapamietaj_id:='';
Edit1.Text:='';
end;
```
</ol>
Możesz już skompilować i uruchomić program.
Listing całego programu został zaprezentowany poniżej (uruchamiałem go na Delphi 2005 więc mogą być drobne różnice w modułach dodanych po słowie uses w Delphi 7 - ale powinniście sobie poradzić)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DBXpress, FMTBcd, StdCtrls, ComCtrls, DB, SqlExpr, Spin;
type
TForm1 = class(TForm)
SQLConnection1: TSQLConnection;
SQLQuery1: TSQLQuery;
ListView1: TListView;
Button1: TButton;
Edit1: TEdit;
Label1: TLabel;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
procedure Button4Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
zapamietaj_id:string;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
lista:TListItem;
begin
ListView1.Items.Clear;
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('SELECT * FROM Kategorie');
SQLQuery1.Active:=True;
while not SQLQuery1.Eof do
begin
lista:=ListView1.Items.Add;
lista.Caption:=SQLQuery1.FieldValues['ID_KATEGORII'];
try
lista.SubItems.Add(SQLQuery1.FieldValues['NAZWA'])
except
lista.SubItems.Add('');
end;
SQLQuery1.Next;
end;
SQLQuery1.Close;
end;
procedure TForm1.Button2Click(Sender: TObject);
var id,i:integer;
nazwa:string;
begin
if (Edit1.Text<>'') then
begin
nazwa:=''''+Edit1.Text+'''';
SQLQuery1.Close;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('INSERT INTO Kategorie VALUES (klucz_glowny_tabeli_kategorie.nextval,'+nazwa+')');
try
SQLQuery1.ExecSQL;
except
showmessage('Wystąpil bląd podczas wstawiania rekordu. Sprawdź, czy wszystkie pola są poprawnie wypelnione')
end;
end;
Button1Click(Sender);
Edit1.Text:='';
SQLQuery1.Active:=False;
end;
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
var
i:integer;
begin
zapamietaj_id:=''''+Item.Caption+'''';
Edit1.Text:=Item.SubItems.Strings[0];
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
if zapamietaj_id<>'' then
begin
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('DELETE FROM Kategorie WHERE ID_KATEGORII='+zapamietaj_id);
SQLQuery1.ExecSQL;
end
else
showmessage('Zaznacz rekord, który chcesz usunąc');
Button1Click(Sender);
zapamietaj_id:='';
Edit1.Text:='';
end;
procedure TForm1.Button3Click(Sender: TObject);
var id,i:integer;
nazwa:string;
begin
if (zapamietaj_id<>'') then
if (Edit1.Text<>'') then
begin
nazwa:=''''+Edit1.Text+'''';
SQLQuery1.Active:=False;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('UPDATE Kategorie SET NAZWA='+nazwa+' WHERE ID_KATEGORII='+zapamietaj_id);
try
SQLQuery1.ExecSQL;
except
showmessage('Wystąpil bląd podczas aktualizacji rekordu. Sprawdź, czy wszystkie pola są poprawnie wypelnione')
end;
end
else
showmessage('Pole Nazwa musi byc uzupelnione')
else
showmessage('Zaznacz wpis, który chcesz zmienic');
Button1Click(Sender);
zapamietaj_id:='';
Edit1.Text:='';
end;
end.
Podsumowanie dbExpress
W części tej zostala zaprezentowana nowoczesna technologia dostępu do baz danych oracle 10g. Dużo więcej informacji znajdziecie w książce.
ODAC
Wstęp
ODAC (Oracle Data Access Components) to kolejna technologia pozwalająca programować bazy danych Oracle 10g, a zarazem pierwsza, która nie jest dostępna po zainstalowaniu Delphi. ODAC zostało stworzone jako alternatywa dla innych technologii, w szczególności dla BDE. ODAC wykorzystuje OCI (Oracle Call Interface), czyli pewnego rodzaju interfejs API (Application Programming Interface) do łączenia się z bazą.
Instalacja
ODAC to komponenty komercyjne, za które trzeba zapłacić. Jednak za darmo można pobrać wersję sześćdziesięciodniową. Ze strony producenta http://crlab.com/odac/ musisz ściągnąć dwa pliki, w przypadku Delphi 7 będą to odac7.exe i oratoolsadd.exe. Instalacja ODAC przebiega inaczej niż większości komponentów ? bardzo przypomina instalację programów w środowisku Windows. Należy po prostu dwa razy kliknąć na pliki exe i postępować zgodnie ze wskazówkami instalatora. Po zainstalowaniu komponentów ODAC trzeba jeszcze zainstalować narzędzia dodatkowe. Kliknij dwukrotnie plik oratoolsadd.exe, potwierdź zamiar instalacji i postępuj zgodnie z instrukcjami instalatora. Proces instalacji jest prosty, więc nikt nie powinien mieć problemów.
Paleta komponentów ODAC
Po zainstalowaniu komponentów ODAC w Delphi pojawi się nowa paleta komponentów, Oracle Access:
OraSession ? komponent służący do nawiązywania i kontrolowania połączenia z bazą danych, OraQuery ? komponent służący do przechowywania zbioru rekordów i wykonywania zapytań SQL, OraSmart (SmartQuery) ? alternatywa dla komponentu OraQuery, OraSQL ? komponent służący do wykonywania instrukcji PL/SQL, procedur składowanych itp., OraTable ? odpowiednik komponentu Table w technologii BDE, służy do przechowywania zbioru danych i wykonywania operacji na jednej tabeli, OraStoredProc ? komponent służący do wykonywania procedur i funkcji składowanych, OraUpdateSQL ? odpowiednik komponentu UpdateSQL występującego w technologii BDE, OraNestedTable ? komponent służący do obsługi tabel zagnieżdżonych, OraDataSource ? odpowiednik komponentu DataSource, OraScript ? komponent służy np. do wykonywania sekwencji, OraPackage ? komponent służący do wykonywania pakietów PL/SQL, OraAlert ? komponent pozwala na przekazywanie informacji pomiędzy sesjami, OraLoader ? komponent pozwala na szybkie załadowanie danych do bazy danych, OraSQLMonitor ? komponent służący do monitorowania zapytań SQL i zmian zachodzących w bazie danych, obsługiwanej przez technologię ODAC. Odpowiednik narzędzia SQL Monitor, OraErrorHandler ? komponent służący do tłumaczenia komunikatów błędów, BDESession ? pozwala integrować komponenty ODAC z aplikacjami stworzonymi w technologii BDE, ConnectDialog ? służy do przechowywania nazwy użytkownika, hasła i nazwy serwera baz danych, VirtualTable ? komponent służący do składowania zbioru danych w pamięci, OraProvider </ul>Ja omówię tylko zastosowanie komponentu OraSQL - po więcej informacji odsyłam do książki.
Tworzenie połączenia z bazą danych
Żeby połączyć się z bazą danych stworzoną w środowisku Oracle 10g za pomocą komponentów ODAC, należy umieścić na formularzu komponent OraSession1. Następnie trzeba dwukrotnie kliknąć ten komponent lub kliknąć prawym klawisz myszy i z menu podręcznego wybrać opcję Session Editor. Ukaże się nowe okno, w którym należy wypełnić kilka pól.
W polu UserName należy wpisać nazwę użytkownika bazy danych (u mnie artur), w polu Password hasło tego użytkownika (u mnie artur). Z rozwijanej listy Server należy wybrać nazwę bazy danych ? w moim przypadku orcl. Pole Home pozwala na wybór serwera Oracle, z którym będziemy się łączyć - domyślnie ta opcja jest uzupełniona.
OraSQL
Komponent OraSQL pozwala na wykonywanie nie tylko zapytań SQL, ale również bloków języka PL/SQL. Zaprezentuję działanie komponentu OraSQL na przykładzie - Napiszę aplikację, która pozwoli na wykonywanie bloków PL/SQL i w niektórych wypadkach zaprezentuje wyniki.
Umieść na formatce komponent OraSession1 i skonfiguruj połączenie z bazą danych. Umieść na formatce komponent OraSQL1 i sprawdź, czy jego właściwość Session jest ustawiona na OraSession1. Umieść na formatce dwa komponenty Memo. Pierwszy będzie służył do wpisywania poleceń PL/SQL, drugi do prezentacji wyników. Zmień właściwość ReadOnly komponentu Memo2 na True, żeby nie można było zmieniać treści prezentowanej w tej kontrolce. Możesz wpisać przykładowy blok PL/SQL w komponencie Memo1. W tym celu kliknij dwukrotnie właściwość Lines i w oknie String List Editor wpisz treść bloku PL/SQL. Ja wpisalem:declare
C NUMBER;
begin
SELECT Count(*)
INTO :C
FROM artur.ksiazki;
end;
Umieść na formatce komponent Button1 i zmień jego właściwość Caption na Wykonaj blok PL/SQL.
Oprogramuj zdarzenia onShow i onDestroy formularza. W zdarzeniu onShow będzie następowało połączenie z bazą danych, w zdarzeniu onDestroy rozłączanie z bazą danych
procedure TForm1.FormShow(Sender: TObject);
begin
OraSession1.Connect; //połącz
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
OraSession1.Disconnect; //rozłącz
end;
Oprogramuj zdarzenie onClick przycisku Button1. Naciśnięcie przycisku będzie powodowało wykonanie bloku PL/SQL.
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
//wczytaj zawartość pola Memo do właściwości SQL komponentu OraSQL1
OraSQL1.SQL :=Memo1.Lines;
//sprawdź, czy wśród parametrów jest parametr, który nie ma określonego typu
for i := 0 to OraSQL1.Params.Count-1 do
//jeśli tak jest to ...
if OraSQL1.Params[i].DataType = ftUnknown then
//... przypisz typ string parametrowi
OraSQL1.Params[i].DataType := ftString;
OraSQL1.Execute; //wykonaj blok PL/SQL
end;
W pętli wyszukiwane są parametry bloku Pl/SQL. Jeśli dowolny z parametrów nie ma zadeklarowanego typu, to przypisujemy mu typ łańcuchowy, ponieważ każdy parametr musi mieć zdefiniowany typ.
Oprogramuj zdarzenie AfterExecution komponentu OraSQL1. Zdarzenie to zachodzi po wykonaniu bloku PL/SQL. My w tym zdarzeniu wypiszemy nazwy i wartości parametrów.procedure TForm1.OraSQL1AfterExecute(Sender: TObject; Result: Boolean);
var
i:integer;
begin
if Result then //jeśli coś zostało zwrócone
begin
Memo2.Lines.Clear; //wyczyść komponent Memo2
//w pętli wypisz nazwy wszystkich parametrów i ich wartości
for i := 0 to OraSQL1.Params.Count-1 do
Memo2.Lines.Add(OraSQL1.Params[i].Name + ' = ' + OraSQL1.Params[i].AsString);
end
else //w przeciwnym wypadku wyświetl komunikat
showmessage('Nic nie zostało zwrócone lub wystąpił błąd');
end;
</ol>
Nazwę parametru można uzyskać poprzez wywołanie instrukcji
OraSQL1.Params[i].Name
natomiast jego wartość można uzyskać np. poprzez instrukcję
OraSQL1.Params[i].AsString.
Cały listing programu wygląda nastepująco:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DBAccess, Ora, DB;
type
TForm1 = class(TForm)
OraSession1: TOraSession;
OraSQL1: TOraSQL;
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
procedure FormShow(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure OraSQL1AfterExecute(Sender: TObject; Result: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
OraSession1.Connect;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
OraSession1.Disconnect;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
OraSQL1.SQL :=Memo1.Lines;
for i := 0 to OraSQL1.Params.Count-1 do
if OraSQL1.Params[i].DataType = ftUnknown then
OraSQL1.Params[i].DataType := ftString;
OraSQL1.Execute;
end;
procedure TForm1.OraSQL1AfterExecute(Sender: TObject; Result: Boolean);
var
i:integer;
begin
if Result then
begin
Memo2.Lines.Clear;
for i := 0 to OraSQL1.Params.Count-1 do
Memo2.Lines.Add(OraSQL1.Params[i].Name + ' = ' + OraSQL1.Params[i].AsString);
end
else
showmessage('Nic nie zostało zwrócone lub wystąpił błąd');
end;
end.
Podsumowanie ODAC
W części tej zostala zaprezentowana nowoczesna technologia dostępu do baz danych oracle 10g - ODAC, która nie jest standardowo dostępna w Delphi. Dużo więcej informacji znajdziecie w książce - m.in znajdziecie tam obsługę atrybutów typu BLOB za pomocą ODAC i tworzenie aplikacji internetowych za pomocą ODAC i IntraWeb.
Tworzenie niestandardowej siatki
DBGrid jest złożoną kontrolką. Posiada wiele opcji i możliwości. Wiele z tych opcji jest jednak nieznanych. W książce znajdziecie sposoby:
kolorowania siatki, tworzenia siatki z polem wyboru, tworzenia siatki pozwalajacej wyświetlać grafikę, tworzenia siatki pozwalajacej na zaznaczanie wielu rekordów, tworzenia siatki z polem Memo </ul>Teraz zaprezentuję tylko sposób dopasowywania szerokości kolumn do zawartości siatki.
Dopasowanie szerokości kolumn
Bardzo często deklarując atrybut typu łańcuchowego w Oracle rezerwujemy wielkość pamięci dużo większą niż ten atrybut będzie faktycznie przechowywał. Np. deklarując atrybut Nazwisko z tabeli Autorzy zarezerwowaliśmy dla niego 30 znaków, choć bardzo rzadko można spotkać nazwiska dłuższe niż 20-literowe. Jeśli teraz napiszesz aplikację w Delphi i wyświetlisz dane w DBGrid, to okaże się, że kolumna tabeli przechowująca określony atrybut jest po prostu za szeroka i że trzeba przewijać siatkę, żeby zobaczyć pozostałe kolumny. Można temu zaradzić tworząc odpowiednią procedurę, która najpierw obliczy w pikselach długość najdłuższego wpisu w danej kolumnie, a następnie dopasuje jej szerokość do obliczonej wartości.
procedure Ustaw_dlugosc_siatki(DBGrid: TDBgrid);
const
dodatkowa_dlugosc = 10;
var
pomoc, n: Integer;
max_dlugosc: array [0..30] of Integer;
begin
with DBGrid do
begin
Canvas.Font := Font;
//zapamiętanie długości napisów w tytułach kolumn
for n := 0 to Columns.Count - 1 do
max_dlugosc[n] := Canvas.TextWidth(Fields[n].FieldName) + dodatkowa_dlugosc;
DataSource.DataSet.First;
//jeśli pole jest dłuższe niż długość kolumny, to ustawiamy nowy max_dlugosc
while not DataSource.DataSet.EOF do
begin
for n := 0 to Columns.Count - 1 do
begin
pomoc := Canvas.TextWidth(trim(Columns[n].Field.DisplayText)) +
dodatkowa_dlugosc;
if pomoc > max_dlugosc[n] then max_dlugosc[n] := pomoc;
end;
DataSource.DataSet.Next;
end;
//ustawiamy nową szerokość kolumn
DataSource.DataSet.First;
for n := 0 to Columns.Count - 1 do
if max_dlugosc[n] > 0 then
Columns[n].Width := max_dlugosc[n];
end;
end;
W celu zapamiętania szerokości (w pikselach) kolumn zadeklarowaliśmy trzydziestoelementową tablicę max_dlugosc. Dlaczego trzydziestoelementową? Ponieważ rzadko zdarza się, by tabela miała więcej atrybutów. Oczywiście można posłużyć się tablicami dynamicznymi, aby liczba elementów odpowiadała faktycznej liczbie kolumn w siatce, ale nie to jest istotą prezentowanego rozwiązania. Najpierw do tablicy wpisujemy długość tytułów kolumn. Następnie dokonujemy sprawdzenia, czy którekolwiek pole w tej kolumnie ma większą długość niż tytuł kolumny. Jeśli tak, to ustawiamy nową wartość w tablicy max_dlugosc. Na koniec trzeba ustawić szerokość kolumn. Jak pewnie zauważyłeś, do wartości określającej długość napisu dodawana jest wartość przechowywana przez stałą dodatkowa_dlugosc. Należy to zrobić po to, żeby komórka tabeli była odrobinę większa niż długość przechowywanego przez nią napisu.
Aby teraz dopasować szerokość DBGrid należy w zdarzeniu (np. onShow formularza) wywołać tę procedurę
begin
Ustaw_dlugosc_siatki(DBGrid1);
end;
Raportowanie bazy danych Oracle
Rave Reports - raportowanie za pomocą kodu
Teraz pokażemy, w jaki sposób umieszczać w raporcie dane pobrane z bazy danych stworzonej w Oracle 10g. Dane do raportu pobierzemy wykorzystując technologię ADO, lecz bardzo podobnie sporządza się raporty przy użyciu danych pobranych za pomocą innych technologii. Do stworzenia raportów posłużymy się Rave Reports (więcej o raportowaniu w Rave Reports możesz znaleźć w dwóch moich artykułach umieszczonych na 4programmers i oczywiście w książce).
Stwórzmy raport pokazujący ISBN, tytuł, podtytuł i liczbę stron wszystkich pozycji z tabeli Ksiazki.
Umieść na formularzu komponent ADOConnection1 i skonfiguruj łańcuch połączeń. Umieść na formularzu komponenty ADOQuery1, RvSystem1 i Button1. Zmień właściwość Caption komponentu Button1 na Pokaż dane o książkach. Ustaw właściwość Connection komponentu ADOQuery1 na ADOConnection1 W sekcji private formularza umieść deklarację procedury:procedure Raportoksiazkach(Report : TBaseReport);
Oprogramowujemy zdarzenia onPrint komponentu RvSystem1 i onClick komponentu Button1.
procedure TForm1.Button1Click(Sender: TObject);
begin
RvSystem1.Execute;
end;
procedure TForm1.RvSystem1Print(Sender: TObject);
begin
Raportoksiazkach(Sender as TBaseReport);
end;
Pod słowem implementation napisz kod procedury Raportoksiazkach
procedure TForm1.Raportoksiazkach(Report: TBaseReport);
var
i:integer;
begin
//tworzymy tytuł raportu
Report.SetFont('Arial', 15);
Report.NewLine;
Report.PrintCenter('Książki', 4);
Report.NewLine;
Report.NewLine;
Report.ClearTabs;
//ustawiamy właściwości kolumn, jednostkami są cale
Report.SetTab(0.2, pjLeft, 1.7, 0, 0, 0
Report.SetTab(1.9, pjLeft, 2.1, 0, 0, 0);
Report.SetTab(4.0, pjLeft, 2.5, 0, 0, 0);
Report.SetTab(6.5, pjRight, 1.5, 0, 0, 0);
Report.SetFont('Arial', 10);
Report.Bold := True;
//tworzymy odpowiednie nagłówki
Report.PrintTab('ISBN'); //nagłówek pierwszej kolumny
Report.PrintTab('Tytul książki'); //nagłówek drugiej kolumn
Report.PrintTab('Podtytul'); //nagłówek trzeciej kolumny
Report.PrintTab('Liczba stron'); //nagłówek czwartej kolumny
//tworzymy komórki tabeli i uzupełniamy je danymi pobranymi z tabeli Ksiazki
Report.Bold := False;
Report.NewLine;
{zamykamy komponent ADOQuery1, czyścimy jego zawartość SQL, wstawiamy nową treść zapytania i wykonujemy wpisane zapytanie ? standardowa operacja znana z rozdziału 8.}
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT ISBN, Tytul, Podtytul, Liczba_stron FROM Ksiazki');
ADOQuery1.Open;
ADOQuery1.First; //ustawiamy wskaźnik na pierwszy wpis
for i:=1 to ADOQuery1.RecordCount do //dopóki są rekordy w zbiorze danych
begin
//wyświetlij odpowiednie pole
Report.PrintTab(ADOQuery1.FieldByName('ISBN').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Tytul').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Podtytul').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Liczba_stron').AsString);
Report.NewLine; //przejdź do nowej linii
ADOQuery1.Next; //przejdź do następnego rekordu w zbiorze danych
end;
end;
</ol>
Tworzenie raportu kolumnowego z danymi pobranymi z bazy danych nie różni się specjalnie od tworzenia zwykłego raportu kolumnowego. Najpierw tworzony jest nagłówek raportu i nagłówki kolumn tabeli a astępnie za pomocą instrukcji:
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT ISBN, Tytul, Podtytul, Liczba_stron FROM Ksiazki');
ADOQuery1.Open;
wykonywane jest zapytanie SQL i dane przechowywane są przez komponent ADOQuery1 w postaci zbioru danych. Aby wyświetlić wszystkie dane, trzeba ustawić wskaźnik na początek zbioru danych za pomocą instrukcji:
ADOQuery1.First;
Następnie w pętli dane są wypisywane. Do konkretnego pola ze zbioru danych można dostać się za pomocą:
ADOQuery1.FieldByName('Atrybut_tabeli').AsString
Po przejściu do następnej linii w raporcie za pomocą instrukcji
Report.NewLine;
należy przejść do następnego wpisu w zbiorze danych, czyli wykonać instrukcję:
ADOQuery1.Next
Raporty tworzone z danych pobieranych z bazy danych generowane są dłużej niż zwykłe raporty Rave Reports. Związane jest to z czynnościami pobierania danych z bazy Oracle 10g. Dlatego przed ukazaniem się raportu użytkownik będzie mógł zobaczyć okno Report Status informujace o tym ktora strona raportu jest generowana. Po wygenerowaniu wszystkich strona na ekranie zostanie wyświetlony raport.
Cały kod programu tworzącego raport kolumnowy z danych pobranych z bazy został przedstawiony poniżej.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, RpDefine, RpBase, RpSystem, DB, ADODB;
type
TForm1 = class(TForm)
ADOQuery1: TADOQuery;
RvSystem1: TRvSystem;
Button1: TButton;
ADOConnection1: TADOConnection;
procedure RvSystem1Print(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure Raportoksiazkach(Report : TBaseReport);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Raportoksiazkach(Report: TBaseReport);
var
i:integer;
begin
Report.SetFont('Arial', 15);
Report.NewLine;
Report.PrintCenter('Książki', 4);
Report.NewLine;
Report.NewLine;
Report.ClearTabs;
Report.SetTab(0.2, pjLeft, 1.7, 0, 0, 0);
Report.SetTab(1.9, pjLeft, 2.1, 0, 0, 0);
Report.SetTab(4.0, pjLeft, 2.5, 0, 0, 0);
Report.SetTab(6.5, pjRight, 1.5, 0, 0, 0);
Report.SetFont('Arial', 10);
Report.Bold := True;
Report.PrintTab('ISBN');
Report.PrintTab('Tytuł książki');
Report.PrintTab('Podtytuł');
Report.PrintTab('Liczba stron');
Report.Bold := False;
Report.NewLine;
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT ISBN, Tytul, Podtytul, Liczba_stron FROM Ksiazki');
ADOQuery1.Open;
ADOQuery1.First;
for i:=1 to ADOQuery1.RecordCount do
begin
Report.PrintTab(ADOQuery1.FieldByName('ISBN').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Tytul').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Podtytul').AsString);
Report.PrintTab(ADOQuery1.FieldByName('Liczba_stron').AsString);
Report.NewLine;
ADOQuery1.Next;
end;
end;
procedure TForm1.RvSystem1Print(Sender: TObject);
begin
Raportoksiazkach(Sender as TBaseReport);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
RvSystem1.Execute;
end;
end.
Podsumowanie
Wydaję mi się, że w artykule tym przedstawiłem dużo ciekawych aspektów programowania baz danych Oracle 10g w środowisku Delphi. Wybaczcie, jeśli artykuł nie jest napisany spójnie, ale pamiętajcie, że wybrałem tylko niektore zagadnienia związane z oracle 10g i Delphi (zabrakło np. informacji o transakcjach, a także o tysiącu innych rzeczy). Ale myślę, że i tak artykuł jest dość obszernym źródłem wiedzy. Jest on również reklamą książki "Oracle 10g i Delphi. Programowanie baz danych", której jestem współautorem. Więc jeśli kogoś z Was przekonałem w ten sposób, że warto kupić tę książkę, to jest mi miło z tego powodu i odsyłam do strony http://helion.pl/ksiazki/oradel.htm
Przepraszam natomiast wszystkich tych, którym przeszkadza to, że "wieje" od tego artykułu reklamą - nie czytajcie tych zdań (stwierdzeń), które zaczynają się od słów "więcej informacji znajdziecie..." :)
AnyDac - świetne i darmowe komponenty do współpracy z Oracle i innymi popularnymi bazami danych.
Witam, Bardzo dobra książka, niestety kupiłam ja z myslą ze znajde odpowiedz na moje pytanie i niestety nie znalazłam. Ale dla innych wiadomości warto było kupić. Moze znajdzidzie sie ktos kto zechce mi pomóc. Mam wgrane do bazy tabelkę z nazwą zdjęcia i zdjęciem (StillImage). W sql/plusie wszystko ładnie wyszukuje, np znajdz zdjęcia podobne do 12.jpg ze względu na kolor i jest ok. jednak nie wiem jak podpiąc te zdjęcia na stronie np za pomoca Oracle HTTP Server zeby te zdjęcia pokazywało, a nie tylko sane nazwy zdjęć. Bardzo prosze o pomoc. Prosze o kontakt na maila emmamarta@wp.pl Moze chociaz jakies materiały, artykuły na ten temat. Z góry dziekuje.
Bardzo dobry artykuł. Zresztą jak każdy Artura.
Do zbyszekz10:
Idź się ponapinaj na podwórko ze swoimi waflami. Widać, że z niego zawistny polaczek.
Ktoś wykonał porządną pracę, a drugi zaraz musi po tym jechać.
Jest to dość częsty bląd w pracy z Oraclem. Proponuję poczytać
http://groups.google.com/group/pl.comp.bazy-danych/browse_thread/thread/72a84e6dc02f646a/cedba52c4b67d565?q=ORA+12154+TNS&rnum=1#cedba52c4b67d565
http://forums.oracle.com/forums/thread.jspa?forumID=56&messageID=690549&threadID=240807
Ewentualne niescislosci zawsze mozna poprawic zbyszekz10... kazdy moze klikajac w przycisk "Edycja".... bo ksiazki to sie juz raczej nie poprawi ;)
Reklama czy antyreklama?
Jeśli w tym tekście jest kilka nieścisłości to jak wygląda cała książka?
Polecam zapoznac sie z tekstem "Formatowanie tekstow" w dziale Pomoc :) Dostepny jest specjalny znacznik, ktory sam generuje spis tresci. Poprawilem nieco tekst, lecz nadal niektore elementy nie sa zgodne z XHTML.
Jeśli mogę wtrącić swoje 3 grosze, to powiem, że w tym wypadku mnie to nie przeszkadza. Odwaliłeś kawał dobrej roboty pisząc książkę, więc reklama się należy. A że przy okazji jako autor podzieliłeś się z nami częścią swojej pracy - chwała Ci za to. Byle więcej takich form reklamy - nikt nie kupiłby wtedy przysłowiowego kota w worku, wiemy, za co płacimy :)
Od tygodnia jestem szczęśliwym posiadaczem tej książki .korzystając ze wskazówek zawartych w książce pisze swoja pierwszą aplikacje w BCB + ORACLE .
korzystajac z okazji mam pytanie
z EM i ISQL*PLUS lacze sie z baza bez problemow.natomiast przy probie podlaczenia z aplikacji w technologi dbexpress pojawia sie komunikat ORA12154:TNS:nie mozna wyliczyc nazwy uslugi.
prosze o pomoc