Sign in Join
Wiki copytemporary

SqlDBHowto/de: what changed

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

OldNewLine
11## Einleitung
22
33Diese Seite ist eine Übersetzung der Seite [[SqlDBHowto/nl]]. Der niederländische Text ist für die Übersetzung massgeblich, auch wenn ich mir die Freiheit genommen habe, einige Korrekturen (meiner Meinung nach kleinere Korrekturen) zu machen.\
44
55Ich entschied mich für diese Art der Darstellung um einige Fragen zu beantworten und um zu zeigen, wie Sie ein Problem lösen können. Alle diese Fragen eine Frage nach der anderen zeigen auch, wie ein Tutorial erstellt wird.\
66
77## Verbinden mit einem Datenbankserver
88
99SqlDB verbindet sich nicht direkt mit einem Datenbankserver sondern verwendet einen Client, der mit dem verwendeten Datenbankserver kommuniziert. (Dieser Client wird meist vom Hersteller der Datenbank geliefert und wird lokal auf dem Computer installiert, der sich mit der Datenbank verbinden soll.) SqlDB sendet die Kommandos an die Client-Bibliothek, die sich mit der Datenbank verbindet und ihr die Kommandos übergibt. Unter Windows ist der Client üblicherweise eine .dll Datei, unter Linux eine .so und unter OS/X eine .dylib Datei.\
1010Wenn die Client-Bibliothek richtig installiert ist, kann man sich über eineTSQLConnection Komponente mit der Datenbank verbinden. Für den Zugriff auf die unterschiedlichen Datenbankserver gibt es eine Vielzahl von TSQLConnection Komponenten.\
1111
1212Zum Beispiel kann man sich:
1313
1414- mit der Komponente TIBConnection mit einer Firebird/Interbase Datenbank verbinden
1515- mit der Komponente TPQConnection mit einer PostgreSQL Datenbank verbinden
1616- mit der Komponente TMySQL56Connection mit einer MySQL Datenbank verbinden
1717- usw.
1818
1919Wenn auf ihrem Computer zum Beispiel die MySQL-Client-Bibliothek Version 4.1 installiert ist, sollte eine TMySQL41Connection verwendet werden, unabhängig von der Version des MySQL-Servers.\
2020
2121Obwohl die Details für die verschiedenen Datenbanken differieren, muss man im allgemeinen nur vier Eigenschaften setzen für die Verbindung zum Datenbankserver: den Namen der Datenbank, den Server-Namen oder die IP Adresse, den Benutzernamen und das Passwort. Wenn diese Eigenschaften gesetzt sind, können sie eine Verbindung mit der 'open' Methode herstellen. Wenn die Verbindung fehlschlägt, wird eine EDatabaseError Exception ausgelöst. Verwenden sie die 'connected' Eigenschaft um zu testen, ob die Verbindung zum Datenbank-Server hergestellt wurde. Mit der 'close' Methode beenden sie die Verbindung zum Server.
2222
2323``` pascal
2424 Program ConnectDB
2525
2626 var AConnection : TSQLConnection;
2727
2828 Procedure CreateConnection;
2929 begin
3030 AConnection := TIBConnection.Create(nil);
3131 AConnection.Hostname := 'localhost';
3232 AConnection.DatabaseName := '/opt/firebird/examples/employee.fdb';
3333 AConnection.UserName := 'sysdba';
3434 AConnection.Password := 'masterkey';
3535 end;
3636
3737 begin
3838 CreateConnection;
3939 AConnection.Open;
4040 if Aconnection.Connected then
4141 writeln('Erfolgreich verbunden!')
4242 else
4343 writeln('Es konnte keine Verbindung zur Datenbank erstellt werden. ' +
4444 'Wenn Sie in Ihrem Programm hier weitermachen, dann lösen Sie eine Exception aus.');
4545 AConnection.Close;
4646 AConnection.Free;
4747 end.
4848```
4949
5050Wird eine Exception ausgelöst, dann lesen Sie bitte die Fehlermeldung sorgfältig. Möglicherweise geht der Datenbankserver nicht oder der Benutzername oder das Kennwort ist falsch, oder der Datenbankname oder die IP-Adresse wurden falsch geschrieben. Sagt zum Beispiel, die Fehlermeldung, dass die Client-Bibliothek der Datenbank nicht gefunden wurde, dann überprüfen Sie bitte, ob die Client-Bibliothek der Datenbank korrekt installiert ist.\
5151
5252## Abfragen direkt ausführen / Eine Tabelle erstellen
5353
5454SQLdb - der Name sagt es bereits - funktioniert nur mit Datenbankservern, die Gebrauch von SQL machen. SQL steht für 'Structured Query Language'. SQL ist eine Sprache die entwickelt wurde, um das Arbeiten mit relationalen Datenbanken zu ermöglichen. Jedes Datenbanksystem benutzt einen eigenen Dialekt. Aber die überwiegende Anzahl von SQL Anweisungen ist für alle Datenbanksysteme gleich. Man unterscheidet zwischen Anweisungen, die Informationen zurückgeben, und Anweisungen, die keine Informationen zurückgeben. Wenn sie die Informationen nutzen wollen, die von einer SQL Anweisung zurückgegeben werden, dann müssen die TSQLQuery Komponente verwenden (siehe Daten aus einer Tabelle lesen). Wollen Sie dagegen keine Informationen von Ihrem Datenbankserver verarbeiten, dann müssen Sie die Methode 'ExecuteDirect' der Klasse TSQLConnection verwenden.\
5555
5656Die meisten Datenbank-Server können in einer Transaktion SQL Anweisungen auszuführen. Sie können auch mehrere SQL Anweisungen zu einer Transaktion zusammenfassen. Transaktionen werden mit einem 'StartTransaction' begonnen und mit einem 'commit' beendet. Um Transkationen durchführen zu können enthält sqldb die Komponente TSQLTransaction. Eine SQL-Anweisung, die von sqldb ausgeführt wird, muss immer innerhalb einer Transaktion ausgeführt werden. Auch dann, wenn das Datenbanksystem keine Transaktionen unterstützt.\
5757
5858Wenn Sie einen SQL-Befehl mit TSQLConnection.ExecuteDirect ausführen möchten, müssen Sie zunächst angeben, welche Transkation (TSQLTransaction) verwendet werden soll. Der Transaktion (TSQLTransaction) wiederum, müssen Sie angeben, welche Verbindung (TSQLConnection) verwendet werden soll.\
5959
6060Das folgende Beispiel erstellt eine Tabelle 'TBLNAMES' mit den Feldern 'NAME' und 'ID' und fügt zwei Datensätze ein. Die verwendeten SQL Anweisungen sind nicht erläutert. Für weitere Informationen über die SQL Anweisungen, ihre Verwendung und Schreibweise schauen sie bitte in der Dokumentation ihres Datenbanksystems nach. Die Prozedur 'CreateConnection' ist im Code-Beispiel im Abschnitt Verbinden mit einem Datenbankserver definiert.
6161
6262``` pascal
6363 program CreateTable;
6464
6565 var AConnection : TSQLConnection;
6666 ATransaction : TSQLTransaction;
6767
6868 procedure CreateTransaction;
6969 begin
7070 ATransaction := TSQLTransaction.Create(nil);
7171 ATransaction.Database := AConnection;
7272 end;
7373
7474 begin
7575 CreateConnection;
7676 CreateTransaction;
7777 AConnection.Transaction := ATransaction;
7878 AConnection.Open;
7979 ATransaction.StartTransaction;
8080 AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));');
8181
8282 // Einige Datenbankserver benöigen ein commit, bevor sie eine neu erzeugte Tabelle nutzen können. (Firebird)
8383 // Mit .Commit schließen sie auch die Transaktion.
8484 ATransaction.Commit;
8585
8686 ATransaction.StartTransaction;
8787 AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (1,'Name1');');
8888 AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (2,'Name2');');
8989 ATransaction.Commit;
9090 AConnection.Close;
9191 AConnection.Free;
9292 ATransaction.Free;
9393 end.
9494```
9595
9696## Daten aus einer Tabelle lesen
9797
9898Verwenden sie die TSQLQuery Komponente, um Daten aus einer Tabelle zu lesen. Eine TSQLQuery Komponente muss mit einer TSQLConnection und einer TSQLTransaction Komponente verbunden werden, damit sie funktionieren kann.\
9999Die Themen TSQLConnection und TSQLTransaction wurden in den Abschnitten Verbinden mit einem Datenbankserver und Abfragen direkt ausführen / Eine Tabelle erstellen behandelt.\
100100
101101Wenn TSQLConnection, TSQLTransaction und TSQLQuery verbunden sind, dann werden weitere Einstellungen für TSQLQuery benötigt. TSQLQuery besitzt eine 'SQL' Eigenschaft, die ein TStrings Objekt enthält. Die 'SQL' Eigenschaft enthält eine SQL Anweisung, die ausgeführt werden muss. Wenn alle Daten aus einer Tabelle gelesen werden sollen, dann setzten sie die 'SQL' Eigenschaft auf 'SELECT * FROM tablename;'. Verwenden sie 'open', um die Tabelle auf dem Server auszulesen und die Daten im TSQLQuery dataset abzulegen. Auf die Daten kann über TSQLQuery zugegriffen werden, bis diese mittels 'close' geschlossen wird. TSQLQuery ist eine Unterklasse von TDataset. TDataset besitzt eine 'Fields' Kollektion, die alle Spalten der Tabelle enthält. Das TDataset behält auch den aktuellen Datensatz im Auge. Verwenden sie die Eigenschaften '.First', '.Next', '.Prior' und '.Last', um den aktuellen Datensatz zu ändern. 'Bof' gibt 'True' zurück, wenn der erste Datensatz erreicht ist und 'Eof' gibt 'True' zurück, wenn der letzte Datensatz erreicht ist. Um den Wert eines Feldes im aktuellen Datensatz zu lesen müssen sie zunächst das richtige 'TField' Objekt herausfinden und dann 'AsString', 'AsInteger', etc. verwenden.
102102
103103Hier ist ein Beispiel, das alle Werte aus der im Abschnitt Abfragen direkt ausführen / Eine Tabelle erstellen selbst erstellten Tabelle ausliest.
104104
105105``` pascal
106106 Program ShowData;
107107
108108 var
109109 AConnection : TSQLConnection;
110110 ATransaction : TSQLTransaction;
111111
112112 function GetQuery : TSQLQuery;
113113 var
114114 AQuery : TSQLQuery;
115115 begin
116116 AQuery := TSQLQuery.Create(nil);
117117 AQuery.Database := AConnection;
118118 AQuery.Transaction := ATransaction;
119119 Result := AQuery;
120120 end;
121121
122122 var
123123 Query : TSQLQuery;
124124
125125 begin
126126 CreateConnection;
127127 CreateTransaction;
128128 Query := GetQuery;
129129 Query.SQL.Text := 'select * from tblNames';
130130 AConnection.Open;
131131 Query.Open;
132132 while not Query.Eof do
133133 begin
134134 Writeln('ID: ', Query.FieldByName('Name').AsInteger, 'Name: ' +
135135 Query.FieldByName('Name').AsString);
136136 Query.Next;
137137 end;
138138 Query.Close;
139139 AConnection.Close;
140140 Query.Free;
141141 ATransaction.Free;
142142 AConnection.Free;
143143 end.
144144```
145145
146146(Dieser Code ist natürlich noch nicht komplett. So fehlen z.B. 'try...finally' Blöcke. Wie auch immer der obige Code zeigt den reinen Datenbankcode.) Beachten sie, dass 'TSQLTransaction.StartTransaction' nicht verwendet wird. Das ist nicht notwendig. Wenn TSQLQuery geöffnet wird, wird die SQL Anweisung ausgeführt und wenn keine Transaktion verfügbar ist, dann wird eine Transaktion automatisch gestartet. Der Programmierer muss die Transaktion nicht explizit starten. Das selbe gilt für die von TSQLConnection gehaltene Verbindung. Die Verbindung wird bei Bedarf geöffnet. Die Zeile 'Aconnection.Open' wird nicht wirklich benötigt. Wenn eine TSQLTransaction gelöscht wird, dann wird ein automatischer 'rollback' ausgeführt. Die Änderungen an den Daten im Rahmen der Transaktion gehen verloren.
147147
148148### Warum gibt TSQLQuery.RecordCount immer 10 zurück?
149149
150150Um die Datensätze in einer Datenbank zu zählen verwenden sie '.RecordCount'. Jedoch zeigt '.RecordCount' die Anzahl von Datensätzen, die bereits vom Server geladen sind. Sqldb liest (per Voreinstellung) nicht alle Datensätze ein, wenn TSQLQuery geöffnet wird, sondern nur die ersten 10. Erst wenn auf den elften Datensatz zugegriffen wird, werden die nächsten 10 Datensätze geladen. Durch die Verwendung von '.Last' werden alle Datensätze geladen.
151151
152152Wenn sie die tatsächliche Anzahl von Datensätzen auf dem Server wissen müssen, dann rufen sie erst '.Last' auf und dann '.RecordCount'. Es gibt aber auch eine Alternative. Die Anzahl von Datensätzen, die der Server zurückgibt, wird mit der Methode '.PacketRecords' festgelegt. Der Vorgabewert ist 10. Wenn sie den Wert auf -1 setzen, dann werden alle Datensätze auf einmal geladen.
153153
154154### Lazarus
155155
156156Um die Daten einer Tabelle anzuzeigen können Sie diese (statt mit einer While-Schleife und mit einer Writeln Ausgabe anzuzeigen) die Komponenten von Lazarus verwenden. Gehen sie dazu in der Lazarus IDE in das Register 'SQLdb'. Legen Sie eine TSQLConnection, eine TSQLTransaction und eine TSQLQuery Komponente auf ein Formular. Verbinden Sie die Komponenten über Ihre Eigenschaften (Wie in den obigen Abschnitten bereits erwähnt.). Danach benötigen Sie noch eine TDatasource Komponente aus dem Register 'Data Access'. Diese verbinden Sie über die Eigenschaft 'TDatasource.DataSet' mit der Komponente TSQLQuery. Anschliessend legen Sie ein TDBGrid aus dem Register 'Data Controls' auf das Formular und verbinden die Eigenschaft 'TDBGrid.Datasource' mit der Komponente TDatasource.\
157157
158158Um zu sehen, ob alles funktioniert, stellen Sie in der Lazarus IDE die "Verbunden"-Eigenschaft der TSQLConnection auf 'True'. Die IDE wird sofort versuchen, sich mit dem Datenbankserver zu verbinden. Wenn das funktioniert, können Sie die 'TSQLQuery.Active-Eigenschaft auf 'True' setzen. Ist alles in Ordnung, dann sehen Sie - in der IDE - alle Daten aus der Tabelle auf dem Bildschirm.\
159159
160160## Daten in einer Tabelle ändern
161161
162162Um die Daten in einem Datensatz zu bearbeiten, muss TDataset (von dem TSQLQuery abgeleitet ist) in den Bearbeitungsmodus versetzt werden. Dies kann durch Aufrufen der Methoden '.Edit', '.Insert' oder '.Append' geschehen. Verwenden sie die Methode '.Edit', um den aktuellen Datensatz zu ändern. Verwenden sie die Methode '.Insert', um einen neuen Datensatz an der aktuellen Position einzufügen. Verwenden sie die Methode '.Append', um einen neuen Datensatz am Ende der Tabelle einzufügen. Im Bearbeitungsmodus können sie die Werte der Felder mit der Methode '.Fields' ändern. Verwenden Sie die Methode '.Post', um die neuen Daten auf ihre Gültigkeit zu prüfen. Sind die Daten gültig, dann wird der Bearbeitungsmodus automatisch verlassen. Wenn Sie zu einem anderen Datensatz wechseln - zum Beispiel durch die Verwendung der Methode'.Next' - und der Datensatz befindet sich im Bearbeitungsmodus, dann wird als erstes die Methode '.Post' aufgerufen. Verwenden sie die Methode '.Cancel', um alle Änderungen seit dem letzten Aufruf der Methode '.Post' zu verwerfen und um den Bearbeitungsmodus zu verlassen.
163163
164164``` pascal
165165 Query.Edit;
166166 Query.FieldByName('NAME').AsString := 'Edited name';
167167 Query.Post;
168168```
169169
170170Die Klasse TSQLQuery leitet die Verwendung der gepufferten Updates von der Klasse TBufDataset ab. Gepuffertes Update bedeutet, dass Sie nachdem Sie die Methode '.Post' angewendet haben, die Änderungen im Client sofort sichtbar sind, und zwar **bevor** diese Daten an dem Datenbankserver gesendet wurden. Erst wenn Sie die Methode '.ApplyUpdates' aufrufen, werden die Änderungen an den Datenbankserver und damit an die Datenbank gesendet. Nur dann erlangt der Datenbankserver Kenntnis von allen Änderungen. Die Änderungen werden innerhalb einer Transaktion von TSQLTransaction an den Datenbankserver gesendet. Stellen sie sicher, dass die richtige Transaktion eingestellt ist, bevor Sie die Methode '.ApplyUpdates' aufrufen. Nach dem Ausführen des Updates muss ein Commit ausgeführt werden um die Änderungen dauerhaft in der Datenbank zu speichern.\
171171
172172Das folgende Beispiel zeigt, wie sie die Daten in einer Tabelle ändern und die geänderten Daten mit einer Transaktion an den Datenbankserver senden und mit einem Commit dauerhaft in der Datenbank speichern.\
173173
174174``` pascal
175175 Program EditData;
176176
177177 var AConnection : TSQLConnection;
178178 ATransaction : TSQLTransaction;
179179 Query : TSQLQuery;
180180
181181 begin
182182 CreateConnection;
183183 CreateTransaction;
184184 AConnection.Transaction := ATransaction;
185185 Query := GetQuery;
186186 Query.SQL.Text := 'select * from tblNames';
187187 Query.Open;
188188 Query.Edit;
189189 Query.FieldByName('NAME').AsString := 'Edited name';
190190 Query.Post;
191191 Query.UpdateMode := upWhereAll;
192192 Query.ApplyUpdates;
193193 AConnection.Transaction.Commit;
194194 Query.Free;
195195 ATransaction.Free;
196196 AConnection.Free;
197197 end.
198198```
199199
200200## Wie Sqldb Änderungen an den Datenbankserver sendet
201201
202202In dem Code-Beispiel in Daten in einer Tabelle ändern finden sie die Zeile
203203
204204``` pascal
205205Query.UpdateMode := upWhereAll;
206206```
207207
208208ohne Erläuterung, was dieser Befehl macht. Der beste Weg es herauszufinden besteht darin, die Zeile wegzulassen. Wenn sie die Anweisung weglassen und sich ansonsten genau an den Beispielcode halten, dann erhalten sie die folgende Fehlermeldung:
209209
210-`No update query specified and failed to generate one. (No fields for inclusion in where statement found)`
210+```text
211+No update query specified and failed to generate one. (No fields for inclusion in where statement found)
212+```
211213
212214Um zu verstehen, was schief gegangen ist, müssen sie wissen, wie Änderungen an den Datenbankserver gesendet werden. Der einzige Weg, um Daten in einen SQL-Server zu bekommen, besteht im Ausführen von SQL-Anweisungen. SQL kennt drei Typen von Anweisungen für drei verschiedene Wege der Manipulierung eines Datensatzes. Um einen (neuen) Datensatz zu erstellen, zu ändern oder zu löschen werden die insert, update und delete Anweisungen entsprechend ausgeführt. Eine update Anweisung könnte wie folgt aussehen:
213215
214216``` sql
215217update TBLNAMES set NAME='Edited name' where ID=1;
216218```
217219
218220Um eine Änderung an den Datenbank-Server zu senden, muss sqldb eine Aktualisierungsabfrage erstellen. Um diese Aktualisierungsabfrage zu erstellen, sind drei Dinge erforderlich:\
219221; Der Name der Tabelle: Der Tabellenname wird durch das Parsen (Durchsuchen, Analysieren) der SELECT-Abfrage ermittelt.
220222
221223`UPDATE` oder `INSERT` Abschnitt
222224Dieser enthält die Felder, die geändert werden sollen.
223225
224226`WHERE` Abschnitt
225227Dieser enthält die Felder, die bestimmen, welche Datensätze geändert werden sollen.
226228
227229Jedes Feld (jedes *TField* in *Fields*) besitzt eine ProviderFlags Eigenschaft. Nur Felder mit **pfInUpdate** in *ProviderFlags* werden in dem update oder insert Abschnitt einer query verwendet. Vorgabemäßig ist *pfInUpdate* bei allen Feldern in deren *ProviderFlags* Eigenschaft gesetzt.
228230
229231Welche Felder in der `WHERE`-Klausel verwendet werden müssen hängt vom Abschnitt Update der SQL-Abfrage (Eigenschaft '.SQL.Text') und von der Eigenschaft '.ProviderFlags' (pfInWhere, pfInUpdate, pfInKey, pfHidden) ab. Felder, die mit dem ProviderFlag pfInKey als Schlüsselfelder gekennzeichnet sind müssen in der `WHERE`-Klausel verwendet werden.\
230232Ist ein Feld Teil eines Primärschlüssels der Datenbanktabelle, dann ist für die Eigenschaft '.ProviderFlags' das Flag pfInKey automatisch eingestellt und die Eigenschaft '.UsePrimaryKeyAsKey' gibt den Wert 'True' zurück.\
231233
232234Der Standardwert für die Eigenschaft '.UpdateMode' ihrer Abfrage ist der Wert upWhereKeyOnly. In diesem Update-Modus wird in der WHERE-Klausel über die Eigenschaft '.ProviderFlags' mit dem Wert pfInKey eine oder mehrere Spalte(n) als Schlüsselfeld(er) gekennzeichnet. Wenn Sie für keines der Felder das Flag pfInKey gesetzt haben, dann kommt es zu einer Fehlermeldung. Sie können das Problem auf folgende Weise lösen:\
233235* Hinzufügen eines Primärschlüssels zur Tabelle und setzen des Wertes von TSQLQuery.UsePrimaryKeyAsKey auf 'True'. Beispiel für das Erstellen eines Primärschlüssels:
234236
235237``` pascal
236238 Query.UsePrimaryKeyAsKey := True;
237239```
238240
239241- Setzen des Flags pfInKey für ein oder mehrere Felder im Code. Beispiel für einen zusammengesetzten Schlüssel:
240242
241243``` pascal
242244 Query.FieldByName('Name').ProviderFlags := [pfInKey];
243245 Query.FieldByName('Vorname').ProviderFlags := [pfInKey];
244246```
245247
246248Die **UpdateMode** Eigenschaft kennt zwei weitere mögliche Werte:
247249
248250- 'upWhereAll': Der Wert 'upWhereAll' versorgt alle Felder mit dem Flag 'pfInWhere'. Damit werden alle Felder zur `WHERE`-Klausel hinzugefügt. Als Standard ist dieses Flag bei allen Feldern gesetzt.
249251- 'upWhereChanged': Der Wert 'upWhereChanged' sorgt dafür, dass nur die Felder in der `WHERE`-Klausel verwendet werden, die das Flag 'pfInWhere' haben und die im aktuellen Datensatz verwendet wurden.
250252
251253## Wie führt man eine Abfrage unter der Verwendung von TSQLQuery aus?
252254
253255Neben den Anweisungen, die Daten zurückgeben (siehe Daten in einer Tabelle ändern), gibt es bei SQL Anweisungen, die keine Daten zurückgeben, zum Beispiel `INSERT`, `UPDATE` und `DELETE`. Diese Anweisungen können mittels *TSQLConnection.ExecuteDirect* ausgeführt werden, aber TSQLQuery kann ebenso verwendet werden. Wenn keine Daten zurückgegeben werden, dann verwenden sie *TSQLQuery.ExecSQL* anstatt *TSQLQuery.Open*. Die Methode *TSQLQuery.Open* wird verwendet um ein von einem SQL-Statement zurück gegebenes Dataset zu öffnen.\
254256Die folgende Prozedur erzeugt eine Tabelle mittels TSQLQuery und fügt zwei Datensätze ein.
255257
256258``` pascal
257259 procedure CreateTable;
258260
259261 var Query : TSQLQuery;
260262
261263 begin
262264 Query := GetQuery;
263265 Query.SQL.Text := 'create table TBLNAMES (ID integer, NAME varchar(40));';
264266 Query.ExecSQL;
265267
266268 Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (1,'Name1');';
267269 Query.ExecSQL;
268270
269271 Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (2,'Name2');';
270272 Query.ExecSQL;
271273
272274 Query.Close;
273275 Query.Free;
274276 end;
275277```
276278
277279## Verwendung von Parametern in einer Abfrage
278280
279281Im Code-Beispiel von Wie führt man eine Abfrage unter der Verwendung von TSQLQuery aus? wird die selbe Abfrage zweimal verwendet, nur mit anderen einzusetzenden Werten. Eine bessere Möglichkeit dies zu erledigen ist die Verwendung von Parametern in der Abfrage.
280282
281283Die Syntax von Parametern in Abfragen ist je nach verwendeter Datenbank unterschiedlich. Aber diese Unterschiede können von TSQLQuery gehandhabt werden. Ersetzen sie die Werte in der Abfrage mit einem Doppelpunkt gefolgt von dem Namen des Parameters, den sie verwenden wollen.\
282284Zum Beispiel:
283285
284286``` pascal
285287 Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
286288```
287289
288290Diese Abfrage enthält zwei Parameter: 'ID' und 'NAME'. Um die Parameter zu bestimmen, wird die Abfrage in dem Moment analysiert, wenn der Text von *TSQLQuery.SQL* zugewiesen oder geändert wird. Alle existierenden Parameter werden entfernt und die neuen Parameter zur 'TSQLQuery.Params' Eigenschaft hinzugefügt. Einem Parameter einen Wert zuzuweisen ist ähnlich der Zuweisung eines Werts zu einem Feld im Dataset:
289291
290292``` pascal
291293 Query.Params.ParamByName('Name').AsString := 'Name1';
292294```
293295
294296Sie können der Abfrage mitteilen, welche Art von Daten in dem Parameter gespeichert werden sollen. Der Datentyp des Parameters wird in dem Moment bestimmt, wenn ein Wert das erste Mal dem Parameter zugewiesen wird. Durch die Zuweisung eines Wertes mittels '.AsString', erhält der Parameter den Datentyp 'ftString'. Sie können den Datentyp auch direkt über die 'DataType' Eigenschaft bestimmen. Wenn dem Parameter ein falscher Datentyp zugewiesen wird, dann werden Probleme auftauchen, wenn die Abfrage geöffnet bzw. ausgeführt wird.
295297
296298Das folgende Beispiel erzeugt die selbe Tabelle wie im vorherigen Beispiel, jetzt aber unter Verwendung von Parametern:
297299
298300``` pascal
299301 procedure CreateTableUsingParameters;
300302
301303 var Query : TSQLQuery;
302304 Param_ID,Param_Name: TParam;
303305
304306 begin
305307 Query := GetQuery;
306308 Query.SQL.Text := 'create table TBLNAMES (ID integer, NAME varchar(40));';
307309 Query.ExecSQL;
308310
309311 Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
310312
311313 Param_ID:=TParam.Create(Query.Params,ptInput);
312314 Param_ID.Name:='ID';
313315 Query.Params.AddParam(Param_ID);
314316
315317 Param_Name:=TParam.Create(Query.Params,ptInput);
316318 Param_Name.Name:='Name';
317319 Query.Params.AddParam(Param_Name);
318320
319321 Query.Params.ParamByName('ID').AsInteger := 1;
320322 Query.Params.ParamByName('NAME').AsString := 'Name1';
321323 Query.ExecSQL;
322324
323325 Query.Params.ParamByName('ID').AsInteger := 2;
324326 Query.Params.ParamByName('NAME').AsString := 'Name2';
325327 Query.ExecSQL;
326328
327329 Query.Close;
328330 Query.Free;
329331 end;
330332```
331333
332334Was sofort auffällt, ist, dass dieses Beispiel mehr Code verwendet, als das Beispiel das keine Parameter verwendet. Was ist dann der Vorteil der Verwendung von Parametern? Einer der Gründe ist Geschwindigkeit. Die meisten Datenbankserver unterstützen Parameter.\
333335Mit 'TSQLQuery.Prepare' bestimmen Sie, dass der Datenbankserver bereits reservierte Ressourcen nutzen soll. Der Aufruf der Methode '.Prepare' ist sinnvoll, wenn Sie mehrere Datensätze auf einmal bearbeiten wollen. Mit 'TSQLQuery.unPrepare' bestimmen Sie, dass der Datenbankserver reservierte Resourcen freigeben soll (Das geschieht automatisch.).\
334336Beispiel für '.Prepare':
335337
336338``` pascal
337339 for i := 1 to j do
338340 begin
339341 Query.paramByName('ID').AsInteger := i;
340342 Query.paramByName('Name').AsString := 'Name...';
341343 Query.Prepare;
342344 Query.ExecSQL;
343345 end;
344346```
345347
346348Ein anderer Grund für die Verwendung von prepared statements ist die Vermeidung von [SQL-Injection](http://de.wikipedia.org/wiki/SQL-Injection). Aber in manchen Fällen vereinfacht es auch nur die Programmierung.\
347349
348350## Siehe auch
349351
350-`* `[[Working With TSQLQuery]]`.`
352+```text
353+* Working_With_TSQLQuery.
354+```
351355
352356---
353357*From the Free Pascal wiki, page "SqlDBHowto/de", as it stood on 2020-02-27 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