Rozdział 17. Bazy danych dbExpress

Adam Boduch

W poprzednim rozdziale omawiałem korzystanie z baz danych przy użyciu komponentów BDE. Inną ? moim zdaniem ciekawą ? formą dostępu do baz danych jest technologia dbExpress. Dzięki komponentom z zakładki dbExpress możesz w prosty sposób uzyskać dostęp do najpopularniejszych systemów baz danych, takich jak MS SQL, MySQL, Interbase i Oracle.

1 Aplikacje klient-serwer
     1.1 Narzędzia
     1.2 Komponenty
2 Łączenie z serwerem
     2.3 Kontrola procesu logowania
     2.4 Zdarzenia AfterConnect i AfterDisconnect
3 Jak działa MySQL?
     3.5 Tabele
     3.6 Zapytania
4 Tworzenie tabel
5 Dodawanie rekordów
6 Kasowanie rekordów
     6.7 Procedura kasująca
7 Odczytywanie rekordów
     7.8 Przykładowy program
8 Zmiana wartości rekordów
     8.9 Przykładowy program: spis sprzedanych towarów
9 Inne komponenty dbExpress
10 Programy oparte o dbExpress
11 Podsumowanie

Podstawą korzystania z różnych baz danych są tzw. sterowniki, które umożliwiają dostęp do systemów baz i pełnią rolę pośredników.

Ważnym czynnikiem wpływającym na jakość technologii dbExpress jest to, że są to komponenty międzyplatformowe, zapewniające zgodność z Delphi oraz ze środowiskiem Kylix.

W tym rozdziale:
*dowiesz się, na czym polega tworzenie aplikacji typu klient-serwer;
*nauczysz się komunikować z bazą danych MySQL;
*zaprojektujesz prostą aplikację baz danych, łączącą się z serwerem.

Aplikacje klient-serwer

Architektura baz danych typu klient-serwer polega na łączeniu aplikacji-klienta z serwerem, na którym znajduje się centralna baza danych. Zasada ta jest podobna do omawianej w rozdziale 11. komunikacji za pomocą gniazd. Różnica polega na tym, że na serwerze jest zainstalowany jakiś system baz danych, a my możemy tylko się z nim połączyć.
SQL to skrót od angielskich słów Structured Query Language. Jest to język oparty na specjalnych zapytaniach kierowanych do bazy.

Narzędzia

Podczas pisania tego rozdziału i przygotowywania przykładowych programów posłużę się darmowymi narzędziami, które może łatwo zdobyć każdego, kto ma dostęp do Internetu. Jako serwer wykorzystamy serwer lokalny Apache 1.3. Baza danych oparta będzie na MySQL. Po pierwsze, baza danych MySQL jest dość łatwa w użyciu, bardzo popularna, darmowa i stosunkowo szybka. Serwer Apache także jest darmowy i niezwykle popularny. Oba te programy dostępne są zarówno w wersjach dla Linuksa, jak i dla Windows.

Najnowsza wersja serwera Apache znajduje się na stronie www.apache.org, natomiast serwer baz danych MySQL możesz pobrać ze strony www.mysql.com. Sposób instalacji Apache oraz MySQL możesz znaleźć m.in. na stronie www.4programmers.net. Ze względu na dość znaczne rozmiary tych aplikacji postanowiłem ? z myślą o Czytelnikach, którzy posiadają modemy ? umieścić te aplikacje na dołączonej do książki płycie CD-ROM.

Komponenty

W przykładach z tego rozdziału wykorzystamy komponenty bazodanowe z zakładki dbExpress. Owe komponenty są raczej łatwe w użyciu, jeżeli pozna się zasadę ich działania. Na początku połączenie się z serwerem może sprawić niewielkie problemy, lecz później wszystko powinno pójść gładko.

Łączenie z serwerem

Do połączenia z serwerem MySQL będziemy musieli użyć komponentu TSQLConnection z zakładki dbExpress.

Pierwsza rzecz, jaką musisz zrobić, to skopiowanie do katalogu z programem biblioteki libmysql.dll, która jest wymagana do połączenia. Ów plik możesz znaleźć w pakiecie MySQL jak również na dołączonej do książki płycie CD-ROM, w katalogu ../listingi/17/Connect.

Umieść więc komponent TSQLConnection na formularzu i zmień jego nazwę na MySQL. Następnie będziesz musiał zmienić wartość właściwości ConnectionName na MySQLConnection (rysunek 17.1); spowoduje to automatyczne dopasowanie kilku pozostałych właściwości.

17.1.jpg
Rysunek 17.1. Lista możliwych połączeń

Komponent odczytuje listę sterowników z plików dbxconnections.ini oraz dbxdrivers.ini (u mnie te pliki znajdują się w katalogu E:\Borland Shared\DBExpress). Pliki INI zawierają także parametry, które są wczytywane do właściwości Params w Inspektorze Obiektów.

Aby móc nawiązać połączenie, należy zmodyfikować jeszcze odpowiednie wartości we właściwości Params. Wybierz tę właściwość ? zostanie wyświetlone okno edycji parametrów, takie jak na rysunku 17.2.

17.2.jpg
Rysunek 17.2. Okno edycji parametrów

W tym momencie powinieneś uruchomić serwer MySQL i stworzyć w nim jakąś przykładową bazę danych ? np. delphi.
W oknie edycji parametrów w pozycji Host Name wpisz adres serwera ? w moim przypadku jest to 127.0.0.1. Pozycja Database określa bazę danych, na jakiej odbędą się operacje ? wpisz tutaj nazwę utworzonej bazy danych, czyli delphi. Pozostało jeszcze określenie nazwy użytkownika bazy oraz hasło (pola User_Name oraz Password). Wpisz tutaj nazwę użytkownika i hasło do swojej bazy danych. W moim przypadku ani hasło, ani nazwa użytkownika nie są wymagane, mogę więc usunąć te pola z edytora.

Połączenie ustanowić można poprzez właściwość Connected komponentu TSQLConnection. Właściwość Connected jest typu Boolean ? przypisanie jej wartości True spowoduje próbę połączenia z serwerem:

procedure TMainForm.btnConnectClick(Sender: TObject);
begin
  if MySQL.Connected then
    MySQL.Connected := False
  else MySQL.Connected := True;
end;

Wykonanie powyższego kodu spowoduje albo rozłączenie, albo połączenie z bazą danych ? w zależności od aktualnego stanu.

W przypadku zmiany właściwości LoginPromt na False podczas łączenia nie zostanie wyświetlone okno logowania. Program pobierze nazwę użytkownika oraz hasło z parametrów User_Name oraz Password.

Jeżeli dostęp do Twojej bazy nie wymaga nazwy użytkownika ani hasła, usuń klucze User_Name oraz Password z okna edytora właściwości (rysunek 17.2).

Kontrola procesu logowania

Nie każdy chce, aby przed zalogowaniem komponent wyświetlał okienko, w którym trzeba podać nazwę użytkownika i hasło. Lepszym rozwiązaniem jest umieszczenie na formularzu dwóch etykiet, w których użytkownik będzie mógł wprowadzić swoje hasło oraz nazwę użytkownika. To zadanie można zrealizować, korzystając ze zdarzenia OnLogin:

procedure TMainForm.MySQLLogin(Database: TSQLConnection;
  LoginParams: TStrings);
begin
  LoginParams.Values['User_Name'] := edtLogin.Text;
  LoginParams.Values['password'] := edtPassword.Text;
end;

Zdarzenie to występuje zawsze przed zalogowaniem się do systemu. Powoduje ono przypisanie nazwy użytkownika oraz hasła z etykiet tekstowych.

Zdarzenia AfterConnect i AfterDisconnect

Aby sprawdzić, czy program został już połączony z bazą danych, wystarczy wygenerować dwa zdarzenia: AfterConnect oraz AfterDisconnect. Oba występują po zawarciu połączenia oraz po rozłączeniu z serwerem (rysunek 17.3):

procedure TMainForm.MySQLAfterConnect(Sender: TObject);
begin
  StatusBar.SimpleText := 'Połączony ...';
end;

procedure TMainForm.MySQLAfterDisconnect(Sender: TObject);
begin
  StatusBar.SimpleText := 'Rozłączony...';
end;

17.3.jpg
Rysunek 17.3. Tekst informujący o nawiązaniu połączenia

Jak działa MySQL?

Przed przystąpieniem do dalszych działań musisz opanować podstawy oraz zasady działania bazy danych MySQL.
MySQL (www.mysql.com) jest darmową, opartą na licencji GNU platformą baz danych. Swoją popularność zawdzięcza głównie temu, że jest darmowa ? również w zastosowaniach komercyjnych. Stały rozwój tego programu zapewniają setki programistów, współpracujących przy tworzeniu oraz poprawianiu tej bazy danych.

Tabele

Baza danych jest pojęciem o wielu znaczeniach. W systemie MySQL baza danych jest zbiorem tabel. Natomiast tabela jest uporządkowanym zbiorem kolumn i wierszy, niczym tabela w programie Excel albo Word (rysunek 17.4).

17.4.jpg
Rysunek 17.4. Zasada działania tabel

Na powyższym rysunku przedstawiona jest tabela składająca się z trzech kolumn i zawierająca dwa rekordy. Taka sama idea zastosowana jest w bazach danych (w tym MySQL). Myślę, że to pojęcie jest dla Ciebie już w miarę jasne, chociażby po lekturze poprzedniego rozdziału o aplikacjach BDE.

Zapytania

Z wydawaniem ?rozkazów? bazie danych wiąże się pojęcie zapytań. Zapytania przekazywane do bazy danych nakazują jej wykonanie pewnych czynności: utworzenia tabeli, dodania kolumny, usunięcia kolumny, wstawienia nowego rekordu (wiersza) czy usunięcia bazy danych. Aby zapytanie zostało prawidłowo zinterpretowane przez bazę danych, musi być skonstruowane według odpowiedniej składni. Przykładowo zapytanie nakazujące stworzenie nowej tabeli wygląda tak:

CREATE TABLE users (
  id int(11) NOT NULL auto_increment,
  name varchar(128) NOT NULL default '',
  mail varchar(128) NOT NULL default '',
  UNIQUE KEY id (id)
)

Tworzona tabela będzie się nazywać users oraz będzie posiadać trzy kolumny: id (identyfikator rekordu), name i mail. Przeznaczeniem tej tabeli jest przechowywanie informacji na temat zarejestrowanych użytkowników, a zatem kolumna name może określać nazwę użytkownika (pseudonim, imię lub nazwisko), a mail adres e-mail wpisującej się osoby.
Numer id jest zwiększany za każdym dodaniem rekordu (auto_increment). Maksymalna liczba znaków, jaką może zawierać dana kolumna, to 128 (varchar(128)) ? żadna z kolumn nie może być pusta (NOT NULL), a domyślna wartość to ciąg pusty (default ''). Kolumna id będzie unikatowa (UNIQUE).

MySQL nie rozróżnia małych i wielkich liter w zapytaniach. Oznacza to, że zapytania CREATE TABLE i create table zostaną zinterpretowane tak samo.

Tworzenie tabel

Do utworzenia tabeli przez nasz program będziemy potrzebowali komponentu TSQLDataSet; umieść go na formularzu i nazwij SQL. Kolejnym krokiem jest wybranie z listy SQLConnection komponentu MySQL.

Zapytanie można ustawić we właściwości CommandText, zaznaczając ową właściwość, a następnie naciskając przycisk wielokropka, co spowoduje otwarcie edytora takiego, jak na rysunku 17.5.

17.5.jpg
Rysunek 17.5. Edytor zapytań

W polu SQL wpisz takie oto zapytanie:

CREATE TABLE users (
  id int(11) NOT NULL auto_increment,
  name varchar(128) NOT NULL default '',
  mail varchar(128) NOT NULL default '',
  UNIQUE KEY id (id)
)

Możesz już zamknąć edytor; wpisane zapytanie spowoduje utworzenie tabeli users.

Żeby wysłać zapytanie, należy użyć funkcji ExecDir z naszego komponentu SQL.

Utworzenie tabeli (wysłanie zapytania) realizowane jest przez ten kod:

procedure TMainForm.btnCreateTableClick(Sender: TObject);
begin
  if SQL.ExecSQL(True) = 0 then MessageDlg('Tabela utworzona!', mtInformation, [mbOK], 0);
end;

Funkcja ExecSQL zwraca cyfrę 0, jeżeli operacja się powiodła.

Dodawanie rekordów

Wstawienie rekordu do istniejącej już tabeli odbywa się za pośrednictwem zapytania INSERT. Jeżeli znamy dane, które chcemy umieścić w tabeli, to sformułowanie zapytania nie powinno przysporzyć problemu:

INSERT users SET name='Adam Boduch',mail='[email protected]'

Zwróć uwagę, że nie musimy podawać pierwszego parametru ? id. Baza MySQL automatycznie nada wartość kolumnie id, gdyż przypisaliśmy jej parametr auto_increment.

Na formularzu możesz umieścić dwie etykiety tekstowe, w których użytkownik będzie mógł podać swoje imię oraz adres e-mail (rysunek 17.6). Kod programu prezentuje listing 17.1.

17.6.jpg
Rysunek 17.6. Dodawanie nowego rekordu do bazy

Listing 17.1. Kod źródłowy programu

{
  Copyright (c) 2002 by Adam Boduch <[email protected]>
}

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DBXpress, DB, SqlExpr, StdCtrls, FMTBcd;

type
  TMainForm = class(TForm)
    MySQL: TSQLConnection;
    btnConnect: TButton;
    SQL: TSQLDataSet;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    edtLogin: TEdit;
    edtMail: TEdit;
    btnAdd: TButton;
    procedure btnConnectClick(Sender: TObject);
    procedure MySQLAfterConnect(Sender: TObject);
    procedure MySQLAfterDisconnect(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
  private
    Connected : Boolean;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.btnConnectClick(Sender: TObject);
begin
  if Connected then Connected := False else Connected := True;
  MySQL.Connected := Connected;
end;

procedure TMainForm.MySQLAfterConnect(Sender: TObject);
begin
  btnConnect.Caption := 'Rozłącz';
end;

procedure TMainForm.MySQLAfterDisconnect(Sender: TObject);
begin
  btnConnect.Caption := 'Połącz';
end;

procedure TMainForm.btnAddClick(Sender: TObject);
var
  SQLQuery : String;
begin
  SQLQuery := Format('INSERT INTO users SET name="%s", mail="%s"', [edtLogin.Text, edtMail.Text]);
  SQL.CommandText := SQLQuery;
  if SQL.ExecSQL(True) = 1 then MessageDlg('Rekord został dodany!', mtInformation, [mbOK], 0);
end;

end.

Na samym początku konieczne staje się odpowiednie sformułowanie zapytania (czyli łańcucha), którego wartość przydzielimy właściwości CommandText komponentu TSQLDataSet. Rekord powinien zostać wstawiony do bazy po wykonaniu funkcji ExecSQL.

Jeśli wstawienie zostanie wykonane pomyślnie, funkcja ExecSQL zwróci wartość różną od 0.

Kasowanie rekordów

Jeżeli uznamy, że przy wstawianiu nowej pozycji pomyliliśmy się lub nie jest ona nam już potrzebna ? możemy ją z łatwością usunąć. Do tego służy zapytanie DELETE. Formułując zapytanie, należy podać dane, według których baza usunie rekord (np. numer ID):

DELETE FROM users WHERE id='1'

Takie zapytanie może być tworzone na różny sposób ? tj. różne warunki mogą spowodować usunięcie danych. Kryterium może być nazwa użytkownika:

DELETE FROM users WHERE name='Adam Boduch'

W powyższym przypadku usunięte zostaną wszystkie rekordy, w których kolumna name ma wartość Adam Boduch. Aby zaostrzyć kryterium usuwania danych, można zastosować operatory AND i OR (tak samo, jak w Delphi)

DELETE FROM users SET name='Adam' AND mail='[email protected]'

W końcu może istnieć wiele rekordów, w których kolumna name ma wartość Adam, prawda? Żeby nie usunąć niepotrzebnie danych, zastosujemy operator AND w celu podania również wartości kolumny mail.

Procedura kasująca

W naszym przypadku najlepiej usuwać rekord, biorąc pod uwagę kolumnę id, która w żadnym wypadku nie będzie się powtarzać:

procedure TMainForm.btnDeleteClick(Sender: TObject);
begin
  SQL.CommandText := 'DELETE FROM users where id="1"';
  SQL.ExecSQL(True);
end;

Odczytywanie rekordów

Chyba najtrudniejszym zadaniem w przypadku dbExpress jest odczytywanie rekordów. Samo dbExpress jest w gruncie rzeczy proste do opanowania, lecz odczyt danych wymaga poświęcenia większej ilości czasu i wierszy kodu.
Sam odczyt jest realizowany przez zapytanie SELECT:

SELECT * FROM users

Taka instrukcja pobiera wszystkie rekordy znajdujące się w bazie danych. Możliwe jest zaostrzenie tego kryterium i odczytanie tylko wybranych fragmentów:

SELECT * FROM users WHERE name='Adam'

Powyższe zapytanie wyświetli jedynie rekordy zawierające w kolumnie name wartość Adam.

Po wysłaniu zapytania odczyt konkretnych elementów z tabeli odbywa się za pomocą właściwości FieldValues:

SQL.FieldValues['name']

Nazwę kolumny, którą chcemy odczytać, należy wstawić w nawiasie kwadratowym. Wartość zwracana przez ową właściwość jest typu Variant, więc znika problem konwersji pomiędzy typami (w przypadku, gdyby np. kolumna id była typu Integer).

Jeśli mamy odczytać wiele rekordów, należy to uczynić w pętli for:

  for I := 1 to SQL.RecordCount do
  begin
  { dodaj kolejne wartości }
    ListItem := ListView.Items.Add;
    ListItem.Caption := IntToStr(SQL.FieldValues['id']);
    ListItem.SubItems.Add(SQL.FieldValues['name']);
    ListItem.SubItems.Add(SQL.FieldValues['mail']);
    SQL.Next;
  end;

Właściwość RecordCount zawiera ilość rekordów, które zostały zwrócone przez bazę ? jeśli znamy tę liczbę, możemy rozwiązać problem odczytania wszystkich wierszy.

Zwróć uwagę na przedostatni wiersz ? wywołanie instrukcji Next z komponentu TSQLDataSet. Bez tej instrukcji odczytanie kolejnego rekordu nie byłoby możliwe ? w wyniku jej wykonania komponent przechodzi do następnego elementu.

Przykładowy program

Przed czytaniem wszystkich elementów zwróconych przez bazę należy wywołać metodę Open komponentu TSQLDataSet, a po zakończeniu operacji ? procedurę Close. Pełny kod programu zaprezentowano w listingu 17.2.

Listing 17.2. Odczytywanie oraz kasowanie rekordów z bazy danych

{
  Copyright (c) 2002 by Adam Boduch <[email protected]>
}

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DBXpress, DB, SqlExpr, StdCtrls, FMTBcd, Grids, ValEdit,
  ComCtrls;

type
  TMainForm = class(TForm)
    MySQL: TSQLConnection;
    btnConnect: TButton;
    SQL: TSQLDataSet;
    ListView: TListView;
    btnDelete: TButton;
    procedure btnConnectClick(Sender: TObject);
    procedure MySQLAfterConnect(Sender: TObject);
    procedure MySQLAfterDisconnect(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnDeleteClick(Sender: TObject);
  private
    Connected : Boolean;
    procedure LoadTable;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.btnConnectClick(Sender: TObject);
begin
  if Connected then Connected := False else Connected := True;
  MySQL.Connected := Connected;
end;

procedure TMainForm.MySQLAfterConnect(Sender: TObject);
begin
  btnConnect.Caption := 'Rozłącz';
  btnDelete.Enabled := True;
  LoadTable;
end;

procedure TMainForm.MySQLAfterDisconnect(Sender: TObject);
begin
  btnConnect.Caption := 'Połącz';
  btnDelete.Enabled := False;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// podczas zamknięcia programu ? rozłączenie z serwerem
  MySQL.Connected := False;
end;

procedure TMainForm.LoadTable;
var
  i : Integer;
  ListItem : TListItem;
begin
  ListView.Items.Clear;
  SQL.CommandText := 'SELECT * FROM users'; // zapytanie
  SQL.Open; // odczytaj dane

  for I := 1 to SQL.RecordCount do
  begin
  { dodaj kolejne wartości }
    ListItem := ListView.Items.Add;
    ListItem.Caption := IntToStr(SQL.FieldValues['id']);
    ListItem.SubItems.Add(SQL.FieldValues['name']);
    ListItem.SubItems.Add(SQL.FieldValues['mail']);
    SQL.Next;
  end;

  SQL.Close;
end;

procedure TMainForm.btnDeleteClick(Sender: TObject);
begin
  SQL.CommandText := Format('DELETE FROM users where id="%s"', [ListView.Selected.Caption]);
  SQL.ExecSQL(True);
  LoadTable; // po wykonaniu zapytania ? wywołaj procedurę
end;

end.

Zwróć uwagę, że program oprócz odczytania elementów z bazy danych do komponentu TListViewk potrafi także te elementy usuwać ? służy do tego przycisk btnDelete.

Sam program w działaniu jest przedstawiony na rysunku 17.7.

17.7.jpg
Rysunek 17.7. Dane odczytane z serwera MySQL

Zmiana wartości rekordów

W celu zmiany wartości rekordów wystarczy wysłać do bazy zapytanie SQL UPDATE.

UPDATE users SET name='[email protected]'

Powyższe zapytanie uaktualni wartość kolumny name ? nada jej wartość [email protected]. Problem w tym, że uaktualnienie obejmie wszystkie wiersze danej tabeli. Aby zmienić wartość jednego tylko rekordu, należy dodać warunek WHERE:

UPDATE users SET name='[email protected]' where ID='1'

W powyższym przypadku uaktualnienie dotyczyć będzie jedynie rekordu o wartości ID równej 1.

SQL.CommandText := 'UPDATE users SET name="Jan Kowalski" WHERE name="Adam Boduch"';
SQL.ExecSQL(True);

Powyższy fragment kodu spowoduje uaktualnienie wszystkich rekordów, w których kolumnie name znajduje się łańcuch Adam Boduch. Nowa wartość kolumny name to od tego momentu Jan Kowalski.

Przykładowy program: spis sprzedanych towarów

Na dołączonej do książki płycie CD-ROM znajduje się program wykorzystujący bazę MySQL do umieszczania na serwerze listy sprzedanych towarów. Baza danych przechowuje informację na temat nazwy towaru, ilości sprzedanych sztuk, ceny oraz daty wykonania transakcji. Zapytanie SQL, realizujące stworzenie odpowiedniej tabeli, wygląda tak:

CREATE TABLE towary (
  id int(11) NOT NULL auto_increment,
  towar char(255) NOT NULL default '',
  sztuk smallint(2) NOT NULL default '0',
  cena float NOT NULL default '0',
  data datetime NOT NULL default '0000-00-00 00:00:00',
  UNIQUE KEY id (id)
) TYPE=MyISAM;

Kolumna cena będzie typu zmiennoprzecinkowego, a data ? typu datetime, który umożliwia przechowywanie dat i czasu.

Program będzie się składał z dwóch formularzy: jeden posłuży do odczytywania danych i przedstawienia ich w komponencie TListView, a drugi będzie służył do dodawania nowych rekordów. W praktyce jest to podsumowanie tego wszystkiego, co zaprezentowałem w poprzednich podpunktach rozdziału. Kody źródłowe obu formularzy przedstawione są w listingach 17.3 i 17.4.

Listing 17.3. Kod źródłowy modułu MainFrm.pas

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, DBXpress, FMTBcd, DB, SqlExpr;

type
  TMainForm = class(TForm)
    ListView: TListView;
    GroupBox1: TGroupBox;
    btnConnect: TButton;
    btnInsert: TButton;
    btnRemove: TButton;
    SQL: TSQLConnection;
    Query: TSQLDataSet;
    procedure btnInsertClick(Sender: TObject);
    procedure btnConnectClick(Sender: TObject);
    procedure btnRemoveClick(Sender: TObject);
  private

  public
    procedure LoadTable;
  end;

var
  MainForm: TMainForm;

implementation

uses InsertFrm;

{$R *.dfm}

procedure TMainForm.btnInsertClick(Sender: TObject);
begin
{ wyświetl formularz służący do dodawania kolejnych rekordów }
  InsertForm := TInsertForm.Create(Application);
  InsertForm.ShowModal;
  InsertForm.Free;
end;

procedure TMainForm.LoadTable;
var
  i : Integer;
  ListItem : TListItem;
begin
  ListView.Items.Clear;

  Query.CommandText := 'SELECT * FROM towary'; // odczytanie danych z tabeli
  Query.Open;   

  { przedstaw informacje w komponencie TListView }
  for I := 0 to Query.RecordCount do
  begin
    ListItem := ListView.Items.Add;
    ListItem.Caption := Query.FieldValues['id'];
    ListItem.SubItems.Add(Query.FieldValues['towar']);
    ListItem.SubItems.Add(Query.FieldValues['sztuk']);
    ListItem.SubItems.Add(Query.FieldValues['cena'] + ' zł');
    ListItem.SubItems.Add(Query.FieldValues['data']);
    Query.Next;
  end;

  Query.Close;
end;

procedure TMainForm.btnConnectClick(Sender: TObject);
begin
  SQL.Connected := True; // połącz
  LoadTable;
  SQL.Connected := False;
end;

procedure TMainForm.btnRemoveClick(Sender: TObject);
begin
  SQL.Connected := True; // połącz
  Query.CommandText := Format('DELETE FROM users where id="%s"', [ListView.Selected.Caption]);
  Query.ExecSQL(True);
  LoadTable; // po wykonaniu zapytania ? wywołaj procedurę
  SQL.Connected := False; // rozłącz z serwerem
end;

end.

Listing 17.4. Kod źródłowy modułu InsertFrm.pas

unit InsertFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TInsertForm = class(TForm)
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    btnInsert: TButton;
    edtThi: TEdit;
    edtCount: TEdit;
    edtPrice: TEdit;
    procedure btnInsertClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  InsertForm: TInsertForm;

implementation

uses MainFrm;

{$R *.dfm}

procedure TInsertForm.btnInsertClick(Sender: TObject);
begin
  with MainForm do
  begin
    SQL.Connected := True; // połącz z serwerem
    // wyślij zapytanie
    Query.CommandText := Format('INSERT INTO towary SET towar="%s",sztuk="%s",cena="%s",data=NOW()',
    [edtThi.Text, edtCount.Text, edtPrice.Text]);
    Query.ExecSQL(True);
    LoadTable; // ponownie wyświetl zawartość tabeli
    SQL.Connected := False;
    Close;
  end;
end;

end.

W przypadku, gdy masz na dysku dwie wersje Delphi ? 6 oraz 7 ? mogą pojawić się problemy w korzystaniu z dbExpress, np. błąd Operation Not Supported.

Inne komponenty dbExpress

W zakładce dbExpress ? oprócz komponentów TSQLConnction oraz TSQLDataSet ? znajdują się również komponenty TSQLQuery, TSQLStoredProc, TSQLTable, TSQLMonitor i TSQLSimpleDataSet. Ciekawym komponentem jest TSQLMonitor. Umożliwia on monitorowanie komend przesyłanych pomiędzy komputerami za pomocą komponentu TSQLConnection.

Umieść na formularzu komponent TSQLMonitor i z listy rozwijalnej właściwości SQLConnection wybierz komponent typu TSQLConnection. Zdarzenie OnLogTrace komponentu SQLMonitor występuje w trakcie komunikacji między komputerami.

procedure TMainForm.SQLMonitorLogTrace(Sender: TObject;
  CBInfo: pSQLTRACEDesc);
begin
  Memo.Lines := SQLMonitor.TraceList;
end;

Jak widzisz, w prosty sposób można listę wiadomości wyświetlić w komponencie Memo. SQLMonitor posiada bowiem właściwość TraceList typu TStringList, która zawiera wszystkie wiadomości.

Aby komponent SQLMonitor zaczął działać, należy zmienić właściwość Active na True.

W zdarzeniu OnAfterConnect komponentu TSQLConnection wpisz przykładowy kod, który wykona jakieś zapytanie SQL.

 SQL.CommandText := 'SELECT * FROM users;
  SQL.ExecSQL(True);

Zapytanie SELECT nic nie wnosi do programu, gdyż nie można używać metody ExecSQL ? ma ona za zadanie wykonanie pewnych czynności, które będziemy obserwować podczas działania programu w komponencie Memo. Rysunek 17.8 przedstawia program podczas działania.

17.8.jpg
Rysunek 17.8. Monitorowanie SQL

Komponent TSQLMonitor posiada przydatną właściwość FileName. Dzięki niej monitorowane wiadomości mogą być automatycznie dodawane do pliku określonego właśnie we właściwości FileName.

Pozostałe komponenty z zakładki dbExpress nie oferują nic ponad to, co komponent TSQLDataSet; funkcjonują podobnie jak ich odpowiedniki w BDE.

Programy oparte o dbExpress

Sterowniki baz danych pakietu dbExpress są zawarte w oddzielnych bibliotekach DLL. W celu przeniesienia całej aplikacji na inny komputer należy dołączyć pewne pliki *.dll. Jakie? O tym informuje tabela 17.1.

Tabela 17.1. Biblioteki DLL wymagane w połączeniu z różnymi bazami danych

BibliotekaPrzeznaczenie
dbexpdb2.dllBazy danych DB
dbexpmysql.dllBazy danych MySQL
dbexpmss.dllBazy danych MS SQL
dbexpora.dllBazy danych Oracle
dbexpinf.dllSterowniki Informix
dbexpint.dllBazy danych Interbase

Podsumowanie

Technologia dbExpress jest bardzo efektywna i dość łatwa w użyciu ? zapewnia dostęp do wielu baz danych. Pewnie jeszcze wielokrotnie skorzystasz z dbEpxress i nieraz usłyszysz o tej technologii.

Załączniki:

de25kp.jpg Więcej informacji

Delphi 2005. Kompendium programisty
Adam Boduch
Format: B5, stron: 1048
oprawa twarda
Zawiera CD-ROM
[[Delphi/Kompendium|Spis treści]]

[[Delphi/Kompendium/Prawa autorskie|©]] Helion 2003. Autor: Adam Boduch. Zabrania się rozpowszechniania tego tekstu bez zgody autora.

5 komentarzy

Wsadziłem plik libmysql.dll do Borland/Delphi7/Lib i wywala mi błąd przy prubie polączenia

http://oi53.tinypic.com/2litwkj.jpg

Ej, przed chwilą ściągnąłem plik libmysql.dll (bo mi wywalalo że go nie może załadować) i dalej mi tak pisze
"Unable to Load libmysql.dll"

HELP!

Skąd można ściągnąć komponenty dbExpress do delphi 7 personal?

Niestety przy SQL.Open; wyskakuje dbExpress Error: [0x0003]: Invalid Field Type

NIEROZUMIE! błąd mi nie pasuje do akcji ale na 100% po tej linijce wyskakuje

Chce byc dobrze zrozumiany (bo tytul moze wskazywac inaczej), dbExpress to nie system bazodanowy, a jedynie technologia.