Sign in Join
Wiki copytemporary

Database tutorial Zeos1/de: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Einleitung
22
33Dieses Tutorial hat das Ziel, die Verwendung der Zeos Komponenten anhand praktischer Beispiele zu demonstrieren. Es richtet sich vor allem an Einsteiger. Für das Tutorial greife ich auf Firebird mit der Beispieldatenbank employee.fdb zurück. Ausgangspunkt ist [[Database tutorial SQLdb1/de|dieses]] Tutorial, welches mit den SQLdb Komponenten arbeitet.
44
55## Voraussetzungen
66
77Für dieses Tutorial sollten sie möglichst eine aktuelle Lazarus Version verwenden (mit FPC 2.6.2 oder höher). Sollten die Zeos Komponenten noch nicht installiert sein, dann holen sie das jetzt nach (Package -\> Package-Datei (*.lpk) öffnen ... -\> zcomponent.lpk). Außerdem wird Firebird (möglichst Version 2.5 oder höher) benötigt. Die Beispiele gehen davon aus, dass die Standardvorgaben (SYSDBA und masterkey) nicht verändert wurden.
88
99## Beispiel 1
1010
1111Starten sie ein neues Projekt in Lazarus. Für den Zugriff auf die Datenbank benötigen wir *TZConnection* und *TZQuery* von der Seite 'Zeos Access' (unter diesem Namen sind die Zeos-Komponenten in der Komponentenpalette zu finden). Die erste Komponente regelt die Verbindung zur Datenbank. Das beinhaltet auch die Transaktionssteuerung, so daß dafür keine separate Komponente (so wie bei SQLdb) erforderlich ist. Die zweite Komponente ist für die SQL-Kommandos zuständig. Für die Anzeige der Daten verwenden wir eine *TDBGrid* Komponente, die sie auf der Seite 'Data Controls' finden. Für die Verbindung mit den Datenbankkomponenten benötigen wir noch eine *TDatasource* Komponente von der Seite 'Data Access'. Zum Auslösen der Aktionen verwenden wir einen *TButton* von der Seite 'Standard'. Damit haben wir alle Komponenten, die wir für das erste Beispiel benötigen. Vergrößern sie das TDBGrid noch etwas, damit genügend Platz für die Anzeige der Daten zur Verfügung steht.
1212
1313Als nächstes müssen wir die Komponenten miteinander verbinden. Am einfachsten geht das im Objektinspektor. Man kann die Zuweisungen aber auch im Quelltext vornehmen. Die 'Connection' Eigenschaft von ZQuery1 wird auf 'ZConnection1' gesetzt. Danach setzen sie die 'DataSet' Eigenschaft von Datasource1 auf 'ZQuery1'. Die Anbindung der Anzeigekomponente erfolgt, indem die 'Datasource' Eigenschaft von DBGrid1 auf 'Datasource1' gesetzt wird.
1414
1515Wie kommen jetzt die Daten aus der Datenbank auf den Bildschirm? Zunächst müssen wir ZConnection1 mitteilen, wo sich die employee.fdb befindet (üblicherweise im .../examples/empbuild/ Unterverzeichnis ihrer Firebird-Installation). Sie haben jetzt wieder die Wahl, ob sie auf den Objektinspektor zurückgreifen wollen, oder das Verzeichnis im Quelltext zuweisen wollen. Wir entscheiden uns hier für den Objektinspektor. Ändern sie die 'Database' Eigenschaft von ZConnection1 auf den Pfad zur Datei employee.fdb (z.B. C:\Programme\Firebird\Firebird_2_5\examples\empbuild\EMPLOYEE.FDB). Wenn sie sich den Pfad nicht merken können, dann können sie ihn idR. auch aus ihrem Dateimanager mittels 'kopieren und einfügen' eintragen. Ein Vorteil der Zeos-Komponenten liegt darin, daß man damit auf verschiedene Datenbanken zugreifen kann. Auf welches Datenbanksystem konkret zugegriffen werden soll, wird mit der 'Protocol' Eigenschaft geregelt. In der Liste scheinen die Firebird-Einträge doppelt vorzukommen. Hier muß man etwas aufpassen. Die firebirdd...-Einträge (mit dem doppelten d) beziehen sich auf die Embedded-Version von Firebird. Da wir mit der "normalen" Firebird-Version arbeiten wollen, wählen wir den Eintrag 'firebird-2.5'. Bevor der Datenbank-Server Daten herausrückt, wird er die Berechtigung über Benutzername und Passwort abfragen. Eine ernsthafte Datenbank-Anwendung wird daher beim Programmstart den Benutzer danach fragen, um die Daten im geeigneten Moment an den Datenbank-Server weiterzureichen. Wir werden der Einfachheit halber wieder auf den Objektinspektor zurückgreifen. Ändern sie die 'User' Eigenschaft auf 'SYSDBA' und 'Password' auf 'masterkey'. Um zu prüfen, ob die bisher vorgenommenen Einstellungen formal korrekt sind, können sie die 'Connected' Eigenschaft auf 'True' setzen. Ist der Pfad nicht richtig oder stimmt der Benutzername oder das Passwort nicht, dann erscheint eine Fehlermeldung. War die Verbindung erfolgreich, dann trennen sie diese jetzt wieder (auf 'False' setzen).
1616
1717Trotz der erfolgreichen Verbindung wurden aber immer noch keine Daten angezeigt. Das erklärt sich dadurch, dass wir dem Datenbank-Server auch noch nicht mitgeteilt haben, was er anzeigen soll. Die Datenbank employee.fdb enthält mehrere Tabellen. Wenn sie im Vorfeld die Struktur einer Datenbank nicht kennen, dann können sie auf Werkzeuge wie [FlameRobin](http://www.flamerobin.org/index.php) zurückgreifen, um sich die Inhalte anzuzeigen. Aber auch Lazarus bietet ein Hilfsmittel - den Datenbank-Desktop. Sie finden ihn im /tools/lazdatadesktop/ Unterverzeichnis von Lazarus. Öffnen sie das Projekt lazdatadesktop.lpi und kompilieren sie es (setzt FPC 2.6.2 voraus) (unser Beispielprojekt haben sie natürlich vorher gesichert).
1818
1919[framed|center|Der Datenbank-Desktop in Aktion](/wiki-images/d/df/Datadesktop.png)
2020
2121Zurück zu unserem Beispiel. Wir wollen alle Daten aus der Tabelle 'CUSTOMER' anzeigen. Der SQL Befehl dazu lautet:
2222
23-`select * from CUSTOMER`
23+```text
24+select * from CUSTOMER
25+```
2426
2527Diesen Befehl müssen wir der 'SQL' Eigenschaft von ZQuery1 zuweisen. Im Quelltext unseres Programms würde das so aussehen:
2628
27-`ZQuery1.SQL.Text := 'select * from CUSTOMER';`
29+``` pascal
30+ZQuery1.SQL.Text := 'select * from CUSTOMER';
31+```
2832
2933Wird der Befehl in Textform angegeben, dann muss er in einfache Anführungszeichen eingeschlossen werden. Man könnte natürlich auch den Inhalt einer anderen Komponente zuweisen.
3034
3135Die Abfrage der Daten soll erfolgen, wenn der Benutzer auf den Button klickt. Mit einem Doppelklick auf Button1 erzeugt Lazarus das Grundgerüst der dafür notwendigen Prozedur. In ihrem Quelltext sollte jetzt folgendes stehen:
3236
3337``` pascal
3438procedure TForm1.Button1Click(Sender: TObject);
3539begin
3640
3741end;
3842```
3943
4044Zwischen *begin* und *end* müssen wir jetzt die Anweisungen eingeben, die zum Anzeigen der Daten erforderlich sind. Die 'SQL' Eigenschaft von ZQuery1 kann nur geändert werden, wenn ZQuery1 nicht aktiv ist. Daher schließen wir die Komponente zunächst:
4145
42-`ZQuery1.Close;`
46+```text
47+ZQuery1.Close;
48+```
4349
4450Da wir nicht sicher sein können, ob ZQuery1 noch irgendwelche Daten enthält, rufen wir die 'Clear' Prozedur auf:
4551
46-`ZQuery1.SQl.Clear;`
52+```text
53+ZQuery1.SQl.Clear;
54+```
4755
4856Dann weisen wir der 'SQL' Eigenschaft unsere SQL Anweisung zu:
4957
50-`ZQuery1.SQL.Text := 'select * from CUSTOMER';`
58+``` pascal
59+ZQuery1.SQL.Text := 'select * from CUSTOMER';
60+```
5161
5262Jetzt müssen wir die Verbindung zur Datenbank herstellen und dann die Abfrage öffnen:
5363
54-`ZConnection1.Connected := True;`\
55-`ZQuery1.Open;`
64+``` pascal
65+ZConnection1.Connected := True;
66+ZQuery1.Open;
67+```
5668
5769Wenn sie jetzt ihr Programm kompilieren würden, dann würden die Daten aus der Tabelle 'CUSTOMER' bereits angezeigt werden. Ein ordentliches Programm wird aber spätestens beim Beenden dafür sorgen, dass noch offene Verbindungen zur Datenbank geschlossen werden. Die Nebenwirkungen wären sonst nicht absehbar. Wir verwenden das OnClose Ereignis unseres Formulars (mittels Doppelklick im Objektinspektor erzeugen):
5870
5971``` pascal
6072procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
6173begin
6274
6375end;
6476```
6577
6678Beim Trennen verwenden wir die umgekehrte Reihenfolge wie beim Verbinden:
6779
6880``` pascal
6981 ZQuery1.Close;
7082 ZConnection1.Connected := False;
7183```
7284
7385### Zusammenfassung
7486
7587Wir haben bisher gelernt, wie man mit den Zeos-Komponenten eine Verbindung zu einer Firebird Datenbank herstellt und die Daten einer Tabelle am Bildschirm anzeigt.
7688
7789## Erweiterung von Beispiel 1
7890
7991Wenn sie sich an die bisherigen Schritte gehalten haben, dann sollte ihr Quelltext etwa so aussehen:
8092
8193``` pascal
8294unit Unit1;
8395
8496{$mode objfpc}{$H+}
8597
8698interface
8799
88100uses
89101 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, DBGrids,
90102 StdCtrls, db, ZConnection, ZDataset;
91103
92104type
93105
94106 { TForm1 }
95107
96108 TForm1 = class(TForm)
97109 Button1: TButton;
98110 Datasource1: TDatasource;
99111 DBGrid1: TDBGrid;
100112 ZConnection1: TZConnection;
101113 ZQuery1: TZQuery;
102114 procedure Button1Click(Sender: TObject);
103115 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
104116 private
105117 { private declarations }
106118 public
107119 { public declarations }
108120 end;
109121
110122var
111123 Form1: TForm1;
112124
113125implementation
114126
115127{$R *.lfm}
116128
117129{ TForm1 }
118130
119131procedure TForm1.Button1Click(Sender: TObject);
120132begin
121133 ZQuery1.Close;
122134 ZQuery1.SQL.Clear;
123135 ZQuery1.SQL.Text:='select * from CUSTOMER';
124136 ZConnection1.Connected:= true;
125137 ZQuery1.Open;
126138end;
127139
128140procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
129141begin
130142 ZQuery1.Close;
131143 ZConnection1.Connected:= false;
132144end;
133145
134146end.
135147```
136148
137149Nun wird man aber in den seltensten Fällen den kompletten Inhalt einer Tabelle benötigen. Nehmen wir an, es sollen nur die Kunden aus den USA angezeigt werden. Dafür müsste die SQL Anweisung wie folgt lauten:
138150
139-`select * from CUSTOMER where COUNTRY = 'USA'`
151+```text
152+select * from CUSTOMER where COUNTRY = 'USA'
153+```
140154
141155Diese Anweisung werden wir aus zwei Gründen nicht für unser Beispielprogramm verwenden: Zum einen gibt es ein Problem bei der Verwendung des einfachen Anführungszeichens. Der Compiler würde das Anführungszeichen vor USA als schließendes Zeichen betrachten (das erste Zeichen steht ja vor select from...) und damit die SQL Anweisung ungültig machen. Der zweite und gewichtigere Grund ist die Tatsache, dass bei der Entwicklung des Programms noch gar nicht bekannt ist, welche Einschränkung der Anzeige später vorgenommen werden soll. Der Benutzer soll in seiner Flexibilität nicht eingeschränkt werden. Dazu ersetzen wir zunächst 'USA' durch einen Platzhalter:
142156
143-`select * from CUSTOMER where COUNTRY = :COUNTRY`
157+```text
158+select * from CUSTOMER where COUNTRY = :COUNTRY
159+```
144160
145161Die Platzhalter sind durch den führenden Doppelpunkt gekennzeichnet. Um dem Benutzer die Eingabe des Filterwertes zu ermöglichen, platzieren sie eine *TEdit* Komponente (Seite 'Standard' in der Komponentenpalette) auf ihrem Formular. Löschen sie den Wert der 'Text' Eigenschaft. Über die 'Params' Eigenschaft von TZQuery können wir nun mit dem in TEdit eingegebenem Text unseren Platzhalter ersetzen:
146162
147-`ZQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;`
163+``` pascal
164+ZQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
165+```
148166
149167Der Parameter kann sowohl über seine Position als auch seinen Namen spezifiziert werden. Letzteres dürfte vor allem die Lesbarkeit des Quelltextes verbessern. Insgesamt sollte die Prozedur jetzt so aussehen:
150168
151169``` pascal
152170procedure TForm1.Button1Click(Sender: TObject);
153171begin
154172 ZQuery1.Close;
155173 ZQuery1.SQL.Clear;
156174 ZQuery1.SQL.Text:= 'select * from CUSTOMER where COUNTRY = :COUNTRY';
157175 ZQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
158176 ZConnection1.Connected:= True;
159177 ZQuery1.Open;
160178end;
161179```
162180
163181Sie können jetzt ruhig mit den Einstellungen ein wenig herumspielen. Wenn sie einen Filterwert eingeben, der in der Datenbank nicht vorhanden ist, dann wird eine leere Tabelle angezeigt. Es können jedoch auch ernsthafte Probleme auftreten. Da bei einer Client-Server-Anwendung üblicherweise Client und Server räumlich getrennt sind, ist meist nicht auf den ersten Blick ersichtlich, warum es zu einem Problem gekommen ist. Ist der Server heruntergefahren worden oder hat nur jemand einen Stecker gezogen? Zugriffe auf eine Datenbank sollten daher **immer** in eine try ... except und/oder try ... finally Schleife eingebunden werden. Nur so ist sichergestellt, dass Datenbankfehler abgefangen werden können und der Anwender nicht im Regen stehen gelassen wird. Für unsere Beispielanwendung könnte eine rudimentäre Behandlungsroutine wie folgt aussehen:
164182
165183``` pascal
166184begin
167185 try
168186 ZQuery1.Close;
169187 ...
170188 ZQuery1.Open;
171189 except
172190 on EDatabaseError do
173191 begin
174192 MessageDlg('Fehler','Es ist ein Datenbankfehler aufgetreten.',mtError,[mbOK],0);
175193 Edit1.Text:='';
176194 end;
177195 end;
178196end;
179197```
180198
181199Hier wird jedoch nur eine einfache Meldung ausgegeben.
182200
183201## Siehe auch
184202
185203- [[ZeosDBO]]: Informationen zur Installation von Zeos
186204- [[Zeos tutorial/de]]: Informationen über Zeos
187205
188206---
189207*From the Free Pascal wiki, page "Database tutorial Zeos1/de", as it stood on 2020-02-12 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history