Difference between revisions of "SqlDBHowto/de"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(37 intermediate revisions by 3 users not shown)
Line 23: Line 23:
 
Obwohl 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.
 
Obwohl 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.
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
  Program ConnectDB
 
  Program ConnectDB
 
   
 
   
Line 53: Line 53:
  
 
== Abfragen direkt ausführen / Eine Tabelle erstellen ==
 
== Abfragen direkt ausführen / Eine Tabelle erstellen ==
SQLdb - 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|Daten aus einer Tabelle lesen]].)
+
SQLdb - 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|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.<br />
 
Wollen Sie dagegen keine Informationen von Ihrem Datenbankserver verarbeiten, dann müssen Sie die Methode 'ExecuteDirect' der Klasse TSQLConnection verwenden.<br />
 
<br />
 
<br />
Die meisten Datenbanksysteme führen SQL Anweisungen innerhalb einer Transaktion aus. If you want changes made within a transaction available in other transactions, or have those changes available even after closing the transaction, then you have to 'commit' the transaction. To support transactions Sqldb contains the TSQLTransaction component. A SQL statement that is executed by Sqldb must always be executed within a transaction. Even if the database system does not support transactions. Also, there are database sustems that do support transaction for which TSQLConnection does not (yet) support transaction. Even then, you must use the TSQLTransaction component.
+
Die 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.<br />
 
+
<br />
Um <tt>TSQLConnection.ExecuteDirect</tt> zu verwenden um eine SQL Anweisung auszuführen, müssen sie angeben, welche Transaktion verwendet werden soll. In turn, to use TSQLTransaction you must specify which 'Connection' must be used.
+
Wenn 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.<br />
 
+
<br />
 
Das 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|Verbinden mit einem Datenbankserver]] definiert.
 
Das 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|Verbinden mit einem Datenbankserver]] definiert.
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
  program CreateTable;
 
  program CreateTable;
 
   
 
   
Line 70: Line 70:
 
  procedure CreateTransaction;
 
  procedure CreateTransaction;
 
  begin
 
  begin
   ATransaction := TSQLTransaction.Create;
+
   ATransaction := TSQLTransaction.Create(nil);
 
   ATransaction.Database := AConnection;
 
   ATransaction.Database := AConnection;
 
  end;
 
  end;
Line 98: Line 98:
 
== Daten aus einer Tabelle lesen ==
 
== Daten aus einer Tabelle lesen ==
  
Verwenden 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. Setting the TSQLConnection and TSQLTransaction is discussed in [[#How to connect to a database server? ]] and [[#How to execute direct queries/make a table?]].  
+
Verwenden 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.<br />
 
+
Die Themen TSQLConnection und TSQLTransaction wurden in den Abschnitten [[#Verbinden mit einem Datenbankserver|Verbinden mit einem Datenbankserver]] und [[#Abfragen direkt ausführen / Eine Tabelle erstellen|Abfragen direkt ausführen / Eine Tabelle erstellen]] behandelt.<br />
 +
<br />
 
Wenn 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.
 
Wenn 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 '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.
+
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.
  
  
Below is an example that displays all values of the table as it was made in [[#How to execute direct queries/make a table?]] above.
+
Hier ist ein Beispiel, das alle Werte aus der im Abschnitt [[#Abfragen direkt ausführen / Eine Tabelle erstellen|Abfragen direkt ausführen / Eine Tabelle erstellen]] selbst erstellten Tabelle ausliest.
 
+
<syntaxhighlight lang=pascal>
<syntaxhighlight>
 
 
  Program ShowData;
 
  Program ShowData;
 
   
 
   
  var AConnection : TSQLConnection;
+
  var  
    ATransaction : TSQLTransaction;
+
  AConnection : TSQLConnection;
 +
  ATransaction : TSQLTransaction;
 
   
 
   
  procedure GetQuery : TSQLQuery;
+
  function GetQuery : TSQLQuery;
  var AQuery : TSQLQuery;
+
  var
 +
  AQuery : TSQLQuery;
 
  begin
 
  begin
   AQuery := TSQLQuery.Create;
+
   AQuery := TSQLQuery.Create(nil);
   AQuery.Database := FConnection;
+
   AQuery.Database := AConnection;
   AQuery.Transaction := FTransaction;
+
   AQuery.Transaction := ATransaction;
 
   Result := AQuery;
 
   Result := AQuery;
 
  end;
 
  end;
 
   
 
   
  var Query : TSQLQuery;
+
  var
 +
  Query : TSQLQuery;
 
   
 
   
 
  begin
 
  begin
Line 144: Line 147:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
(Dieser Code ist natürlich noch nicht komplett. So fehlen z.B.  'try...finally' Blöcke. However, the above code intends to show the database code and thus the finishing touches are left out.) 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.
+
(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. Änderungen an den Daten im Rahmen der Transaktion gehen verloren.
+
Wenn eine TSQLTransaction gelöscht wird, dann wird ein automatischer 'rollback' ausgeführt. Die Änderungen an den Daten im Rahmen der Transaktion gehen verloren.
  
 
=== Warum gibt TSQLQuery.RecordCount immer 10 zurück? ===
 
=== Warum gibt TSQLQuery.RecordCount immer 10 zurück? ===
Line 151: Line 154:
 
Um 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.  
 
Um 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.  
  
Wenn 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 '.PacketRecords' Eigenschaft festgelegt. Der Vorgabewert ist 10. Wenn sie den Wert auf -1 setzen, dann werden alle Datensätze auf einmal geladen.
+
Wenn 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.
  
 
=== Lazarus ===
 
=== Lazarus ===
 
+
Um 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.<br />
Lazarus besitzt verschiedene Komponenten, um Daten von einem TDataset auf einem Formular anzuzeigen. Instead of a While-loop and Writeln statements as use avobe, you can use the components to show the data in a table. Place the right TSQLConnection, TSQLTransaction and TSQLQuery components on a form, then connect them and set them properly. In addition you will need a TDatasource, set to 'TDatasource.Dataset' property to the TSQLQuery component you used. ('''Note''' do not set the 'TSQLQuery.Datasource' property to the TDatasource compnent you used. The 'TSQLQuery.Datasource' property is only used only in master-detial tables.) Subsequently you may put a TDBGrid onto the form and set the 'Datasource' property of the grid to the TDatasource component you added before.
+
<br />
 
+
Um 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.<br />
To see if it all works, set the 'Connected' property of the TSQLConnection to 'True' in the Lazarus IDE. The IDE will try to connect to the database server immediately. If this works you can set the 'TSQLQuery.Active' property to 'True'. If everything is right, you will see - within the IDE - all data from the table immediately on the screen.
+
<br />
  
 
== Daten in einer Tabelle ändern ==
 
== Daten in einer Tabelle ändern ==
  
Um die Daten in einem Datensatz zu bearbeiten, muss TDataset (von dem TSQLQuery abgeleitet ist) in den Bearbeitungsmodus versetzt werden. Dies kann durch Aufrufen der '.Edit', '.Insert' oder '.Append' Methoden geschehen. Verwenden sie die '.Edit' Methode, um den aktuellen Datensatz zu ändern. Verwenden sie '.Insert', um einen neuen Datensatz an der aktuellen Position einzufügen. Verwenden sie '.Append', um einen neuen Datensatz am Ende der Tabelle einzufügen. Im Bearbeitungsmodus können sie die Werte der Felder mittels der 'Fields' Eigenschaft ändern. Use 'Post' to validate the new data, if the data is valid then the edit mode is left. If you move to another record - for example by using '.Next' - and the dataset is in edit mode, then first '.Post' is called. Verwenden sie '.Cancel', um alle Änderungen seit dem letzten Aufruf von '.Post' zu verwerfen und den Bearbeitungsmodus zu verlassen.
+
Um 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.
  
 +
<syntaxhighlight lang=pascal>
 
  Query.Edit;
 
  Query.Edit;
 
  Query.FieldByName('NAME').AsString := 'Edited name';
 
  Query.FieldByName('NAME').AsString := 'Edited name';
 
  Query.Post;
 
  Query.Post;
 +
</syntaxhighlight>
  
The above is not the complete story yet. TSQLQuery is derived from TBufDataset which makes use of buffered updates. Buffered update mean that after you called 'Post' the changes in the dataset are visible immediately, but they are not sent to the database server. What does happen is that the changes are maintained in a change log. When the '.ApplyUpdates' method is called, then all changes in the change log are sent to the database. Nur dann erlangt der Datenbankserver Kenntnis von allen Änderungen. Die Änderungen werden an den Server gesendet innerhalb einer Transaktion von TSQLTransaction. Stellen sie sicher, dass die richtige Transaktion eingestellt ist, bevor 'ApplyUpdates' aufgerufen wird. After applying the updates, a commit must be executed to publish or store the changes.
+
Die 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.<br />
 
+
<br />
The below is an example of changing the data in a table, sending the changes to the server and comitting the transaction.
+
Das 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.<br />
  
 +
<syntaxhighlight lang=pascal>
 
  Program EditData;
 
  Program EditData;
 
   
 
   
Line 194: Line 200:
 
   AConnection.Free;
 
   AConnection.Free;
 
  end.
 
  end.
 
+
</syntaxhighlight>
For a discussion of 'UpdateMode' continue reading.
+
<br />
  
 
== Wie Sqldb Änderungen an den Datenbankserver sendet ==
 
== Wie Sqldb Änderungen an den Datenbankserver sendet ==
  
 
In dem Code-Beispiel in [[#Daten in einer Tabelle ändern|Daten in einer Tabelle ändern]] finden sie die Zeile
 
In dem Code-Beispiel in [[#Daten in einer Tabelle ändern|Daten in einer Tabelle ändern]] finden sie die Zeile
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Query.UpdateMode := upWhereAll;
 
Query.UpdateMode := upWhereAll;
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 206: Line 212:
 
  No update query specified and failed to generate one. (No fields for inclusion in where statement found)
 
  No update query specified and failed to generate one. (No fields for inclusion in where statement found)
 
Um 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:
 
Um 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:
<syntaxhighlight>
+
<syntaxhighlight lang="sql">
 
update TBLNAMES set NAME='Edited name' where ID=1;
 
update TBLNAMES set NAME='Edited name' where ID=1;
 
</syntaxhighlight>
 
</syntaxhighlight>
To send a change to the database server, Sqldb must assemble an update query. To assemble the query, three things are needed:
+
Um eine Änderung an den Datenbank-Server zu senden, muss sqldb eine Aktualisierungsabfrage erstellen. Um diese Aktualisierungsabfrage zu erstellen, sind drei Dinge erforderlich:<br />
; Der Name der Tabelle : The table name is retrieved from parsing the select query, although this doesn't always work.  
+
; Der Name der Tabelle: Der Tabellenname wird durch das Parsen (Durchsuchen, Analysieren) der SELECT-Abfrage ermittelt.
 
; <tt>UPDATE</tt> oder <tt>INSERT</tt> Abschnitt: Dieser enthält die Felder, die geändert werden sollen.
 
; <tt>UPDATE</tt> oder <tt>INSERT</tt> Abschnitt: Dieser enthält die Felder, die geändert werden sollen.
 
; <tt>WHERE</tt> Abschnitt: Dieser enthält die Felder, die bestimmen, welche Datensätze geändert werden sollen.
 
; <tt>WHERE</tt> Abschnitt: Dieser enthält die Felder, die bestimmen, welche Datensätze geändert werden sollen.
Line 216: Line 222:
 
Jedes 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.
 
Jedes 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.
  
Which fields are used in the <tt>WHERE</tt> clause depends on the ''UpdateMode'' property of the query and the ''ProviderFlags'' property of the fields. Fields with ''pfInkey'' in their ''ProviderFlags'' are always used in the <tt>WHERE</tt> clause. A field will have the ''pfInKey'' flag set automatically if the field is part of the primary key of the table and 'TSQLQuery.UsePrimaryKeyAsKey' returns 'True'.
+
Welche Felder in der <tt>WHERE</tt>-Klausel verwendet werden müssen hängt vom Abschnitt Update der SQL-Abfrage (Eigenschaft '.SQL.Text') und von der Eigenschaft '.ProviderFlags' (<i>pfInWhere, pfInUpdate, pfInKey, pfHidden</i>) ab. Felder, die mit dem ProviderFlag <i>pfInKey</i> als Schlüsselfelder gekennzeichnet sind müssen in der <tt>WHERE</tt>-Klausel verwendet werden.<br />
 
+
Ist ein Feld Teil eines Primärschlüssels der Datenbanktabelle, dann ist für die Eigenschaft '.ProviderFlags' das Flag <i>pfInKey</i> automatisch eingestellt und die Eigenschaft '.UsePrimaryKeyAsKey' gibt den Wert '<i>True</i>' zurück.<br />
The default value for ''UpdateMode'' of the query is ''upWhereKeyOnly''. In this update mode only fields with ''pfInkey'' in their ''ProviderFlags'' property are used in the <tt>WHERE</tt> clause. If none of the fields have their ''pfInKey'' flag set, then no fields are available for the <tt>WHERE</tt> clause and the error message from the beginning of this section will be returned. Sie können das Problem lösen durch:
+
<br />
* Hinzufügen eines Primärschlüssels zur Tabelle und setzen von ''TSQLQuery.UsePrimaryKeyAsKey'' auf 'True', oder
+
Der Standardwert für die Eigenschaft '.UpdateMode' ihrer Abfrage ist der Wert <i>upWhereKeyOnly</i>. In diesem Update-Modus wird in der WHERE-Klausel über die Eigenschaft '.ProviderFlags' mit dem Wert <i>pfInKey</i> eine oder mehrere Spalte(n) als Schlüsselfeld(er) gekennzeichnet. Wenn Sie für keines der Felder das Flag <i>pfInKey</i> gesetzt haben, dann kommt es zu einer Fehlermeldung. Sie können das Problem auf folgende Weise lösen:<br />
* Setzen des ''pfInkey'' Flags für ein oder mehrere Felder im Code.
+
* 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:
 
+
<syntaxhighlight lang=pascal>
Die '''UpdateMode''' Eigenschaft kennt zwei weitere mögliche Werte. 'upWhereAll' can be used to add all fields with the 'pfInWhere' flag set to the <tt>WHERE</tt> clause. By default all fields have this flag set. 'upWhereChanged' can be used to add only those fields that have the 'pfInWhere' flag set '''and''' that are changed in the current record.
+
  Query.UsePrimaryKeyAsKey := True;
 
+
</syntaxhighlight>
== How to execute a query using TSQLQuery? ==
+
* Setzen des Flags <i>pfInKey</i> für ein oder mehrere Felder im Code. Beispiel für einen zusammengesetzten Schlüssel:
 
+
<syntaxhighlight lang=pascal>
Neben den Anweisungen, die Daten zurückgeben (siehe [[#How to read data from a table?]]), gibt es  bei SQL Anweisungen, die keine Daten zurückgeben, zum Beispiel <tt>INSERT</tt>, <tt>UPDATE</tt> und <tt>DELETE</tt>. Diese Anweisungen können mittels ''[[#How to execute direct queries/make a table?|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''. Use ''TSQLQuery.Open'' to open the dataset returned by the SQL statement.  
+
  Query.FieldByName('Name').ProviderFlags := [pfInKey];
 +
  Query.FieldByName('Vorname').ProviderFlags := [pfInKey];
 +
</syntaxhighlight>
 +
Die '''UpdateMode''' Eigenschaft kennt zwei weitere mögliche Werte:
 +
* 'upWhereAll': Der Wert 'upWhereAll' versorgt alle Felder mit dem Flag 'pfInWhere'. Damit werden alle Felder zur <tt>WHERE</tt>-Klausel hinzugefügt. Als Standard ist dieses Flag bei allen Feldern gesetzt.
 +
* 'upWhereChanged': Der Wert 'upWhereChanged' sorgt dafür, dass nur die Felder in der <tt>WHERE</tt>-Klausel verwendet werden, die das Flag 'pfInWhere' haben und die im aktuellen Datensatz verwendet wurden.
 +
<br />
  
 +
== Wie führt man eine Abfrage unter der Verwendung von TSQLQuery aus? ==
 +
Neben den Anweisungen, die Daten zurückgeben (siehe [[#Daten in einer Tabelle ändern|Daten in einer Tabelle ändern ]]), gibt es  bei SQL Anweisungen, die keine Daten zurückgeben, zum Beispiel <tt>INSERT</tt>, <tt>UPDATE</tt> und <tt>DELETE</tt>. Diese Anweisungen können mittels ''[[#Abfragen direkt ausführen / Eine Tabelle erstellen|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.
 +
<br />
 
Die folgende Prozedur erzeugt eine Tabelle mittels TSQLQuery und fügt zwei Datensätze ein.
 
Die folgende Prozedur erzeugt eine Tabelle mittels TSQLQuery und fügt zwei Datensätze ein.
 
+
<syntaxhighlight lang=pascal>
 
   procedure CreateTable;
 
   procedure CreateTable;
 
    
 
    
Line 248: Line 263:
 
     Query.Free;
 
     Query.Free;
 
   end;
 
   end;
 +
</syntaxhighlight>
 +
<br />
  
 
== Verwendung von Parametern in einer Abfrage ==
 
== Verwendung von Parametern in einer Abfrage ==
  
Im Code-Beispiel von [[#How to execute a query using TSQLQuery?]] 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.  
+
Im Code-Beispiel von [[#Wie führt man eine Abfrage unter der Verwendung von TSQLQuery aus?|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.  
  
Die 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. Zum Beispiel:
+
Die 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.<br />
 +
Zum Beispiel:
 +
<syntaxhighlight lang=pascal>
 
   Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
 
   Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
 +
</syntaxhighlight>
 
Diese Abfrage enthält zwei Parameter: 'ID' und 'NAME'.
 
Diese 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:
 
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:
 +
<syntaxhighlight lang=pascal>
 
   Query.Params.ParamByName('Name').AsString := 'Name1';
 
   Query.Params.ParamByName('Name').AsString := 'Name1';
 +
</syntaxhighlight>
 
Sie 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.
 
Sie 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.
  
 
Das folgende Beispiel erzeugt die selbe Tabelle wie im vorherigen Beispiel, jetzt aber unter Verwendung von Parametern:
 
Das folgende Beispiel erzeugt die selbe Tabelle wie im vorherigen Beispiel, jetzt aber unter Verwendung von Parametern:
 
+
<syntaxhighlight lang=pascal>
 
   procedure CreateTableUsingParameters;
 
   procedure CreateTableUsingParameters;
 
    
 
    
Line 275: Line 297:
 
   
 
   
 
     Param_ID:=TParam.Create(Query.Params,ptInput);
 
     Param_ID:=TParam.Create(Query.Params,ptInput);
     Params.Name:='ID';
+
     Param_ID.Name:='ID';
 
     Query.Params.AddParam(Param_ID);
 
     Query.Params.AddParam(Param_ID);
 
   
 
   
 
     Param_Name:=TParam.Create(Query.Params,ptInput);
 
     Param_Name:=TParam.Create(Query.Params,ptInput);
     Params.Name:='Name';
+
     Param_Name.Name:='Name';
 
     Query.Params.AddParam(Param_Name);
 
     Query.Params.AddParam(Param_Name);
 
   
 
   
Line 293: Line 315:
 
     Query.Free;
 
     Query.Free;
 
   end;
 
   end;
 
+
</syntaxhighlight>
Beachten sie, dass dieses Beispiel mehr Quelltext benötigt als das Beispiel ohne Parameter. Was ist dann der Vorteil der Verwendung von Parametern? Geschwindigkeit ist einer der Punkte. Das Beispiel mit Parametern wird schneller ausgeführt, da die Abfrage nur einmal analysiert werden muss. TSQLQuery analysiert die Abfrage zwar nur einmal, aber auch der Datenbankserver analysiert die Abfrage nur einmal. Die meisten Datenbanksysteme unterstützen Parameter. Whenever a query is used more than once with different values for the parameter each time, then the database server only parses the query and plans the query only once making execution considerably faster.
+
Was 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.<br />
Use 'TSQLQuery.Prepare' to determine the moment the query is parsed and planned by the database server. Use 'TSQLQuery.UnPrepare' to make sure the query is parsed and planned every time by the data server.
+
Mit '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.).<br />
Ein anderer Grund für die Verwendung von prepared statements ist die Vermeidung von [http://de.wikipedia.org/wiki/SQL-Injection SQL-Injection]. Aber in manchen Fällen vereinfacht es auch nur die Programmierung.
+
Beispiel für '.Prepare':
 +
<syntaxhighlight lang=pascal>
 +
  for i := 1 to j do
 +
  begin
 +
    Query.paramByName('ID').AsInteger := i;
 +
    Query.paramByName('Name').AsString := 'Name...';
 +
    Query.Prepare;
 +
    Query.ExecSQL;
 +
  end;
 +
</syntaxhighlight>
 +
Ein anderer Grund für die Verwendung von prepared statements ist die Vermeidung von [http://de.wikipedia.org/wiki/SQL-Injection SQL-Injection]. Aber in manchen Fällen vereinfacht es auch nur die Programmierung.<br />
  
 
== Siehe auch ==
 
== Siehe auch ==
  
 
  * [[Working_With_TSQLQuery]].
 
  * [[Working_With_TSQLQuery]].
 
[[Category:Databases/de]]
 

Latest revision as of 13:09, 27 February 2020

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) Nederlands (nl) polski (pl) 中文(中国大陆)‎ (zh_CN)

Einleitung

Diese 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.

Ich 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.

Verbinden mit einem Datenbankserver

SqlDB 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.
Wenn 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.

Zum Beispiel kann man sich:

  • mit der Komponente TIBConnection mit einer Firebird/Interbase Datenbank verbinden
  • mit der Komponente TPQConnection mit einer PostgreSQL Datenbank verbinden
  • mit der Komponente TMySQL56Connection mit einer MySQL Datenbank verbinden
  • usw.

Wenn 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.

Obwohl 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.

 Program ConnectDB
 
 var AConnection : TSQLConnection;
 
 Procedure CreateConnection;
 begin
   AConnection := TIBConnection.Create(nil);
   AConnection.Hostname := 'localhost';
   AConnection.DatabaseName := '/opt/firebird/examples/employee.fdb';
   AConnection.UserName := 'sysdba';
   AConnection.Password := 'masterkey';
 end;
 
 begin
   CreateConnection;
   AConnection.Open;
   if Aconnection.Connected then
     writeln('Erfolgreich verbunden!')
   else
     writeln('Es konnte keine Verbindung zur Datenbank erstellt werden. ' +
             'Wenn Sie in Ihrem Programm hier weitermachen, dann lösen Sie eine Exception aus.');
   AConnection.Close;
   AConnection.Free;
 end.


Wird 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.

Abfragen direkt ausführen / Eine Tabelle erstellen

SQLdb - 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.

Die 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.

Wenn 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.

Das 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.

 program CreateTable;
 
 var AConnection : TSQLConnection;
     ATransaction : TSQLTransaction;
 
 procedure CreateTransaction;
 begin
   ATransaction := TSQLTransaction.Create(nil);
   ATransaction.Database := AConnection;
 end;
 
 begin
   CreateConnection;
   CreateTransaction;
   AConnection.Transaction := ATransaction;
   AConnection.Open;
   ATransaction.StartTransaction;
   AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));'); 
   
   // Einige Datenbankserver benöigen ein commit, bevor sie eine neu erzeugte Tabelle nutzen können. (Firebird)
   // Mit .Commit schließen sie auch die Transaktion.
   ATransaction.Commit; 
 
   ATransaction.StartTransaction;
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (1,'Name1');'); 
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (2,'Name2');'); 
   ATransaction.Commit; 
   AConnection.Close;
   AConnection.Free;
   ATransaction.Free;
 end.

Daten aus einer Tabelle lesen

Verwenden 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.
Die Themen TSQLConnection und TSQLTransaction wurden in den Abschnitten Verbinden mit einem Datenbankserver und Abfragen direkt ausführen / Eine Tabelle erstellen behandelt.

Wenn 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.


Hier ist ein Beispiel, das alle Werte aus der im Abschnitt Abfragen direkt ausführen / Eine Tabelle erstellen selbst erstellten Tabelle ausliest.

 Program ShowData;
 
 var 
   AConnection : TSQLConnection;
   ATransaction : TSQLTransaction;
 
 function GetQuery : TSQLQuery;
 var
   AQuery : TSQLQuery;
 begin
   AQuery := TSQLQuery.Create(nil);
   AQuery.Database := AConnection;
   AQuery.Transaction := ATransaction;
   Result := AQuery;
 end;
 
 var
   Query : TSQLQuery;
 
 begin
   CreateConnection;
   CreateTransaction;
   Query := GetQuery;
   Query.SQL.Text := 'select * from tblNames';
   AConnection.Open;
   Query.Open;
   while not Query.Eof do
     begin
     Writeln('ID: ', Query.FieldByName('Name').AsInteger, 'Name: ' +
                                   Query.FieldByName('Name').AsString);
     Query.Next;
     end;
   Query.Close;
   AConnection.Close;
   Query.Free;
   ATransaction.Free;
   AConnection.Free;
 end.

(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.

Warum gibt TSQLQuery.RecordCount immer 10 zurück?

Um 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.

Wenn 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.

Lazarus

Um 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.

Um 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.

Daten in einer Tabelle ändern

Um 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.

 Query.Edit;
 Query.FieldByName('NAME').AsString := 'Edited name';
 Query.Post;

Die 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.

Das 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.

 Program EditData;
 
 var AConnection : TSQLConnection;
     ATransaction : TSQLTransaction;
     Query : TSQLQuery;
 
 begin
   CreateConnection;
   CreateTransaction;
   AConnection.Transaction := ATransaction;
   Query := GetQuery;
   Query.SQL.Text := 'select * from tblNames';
   Query.Open;
   Query.Edit;
   Query.FieldByName('NAME').AsString := 'Edited name';
   Query.Post;
   Query.UpdateMode := upWhereAll;
   Query.ApplyUpdates;
   AConnection.Transaction.Commit;
   Query.Free;
   ATransaction.Free;
   AConnection.Free;
 end.


Wie Sqldb Änderungen an den Datenbankserver sendet

In dem Code-Beispiel in Daten in einer Tabelle ändern finden sie die Zeile

Query.UpdateMode := upWhereAll;

ohne 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:

No update query specified and failed to generate one. (No fields for inclusion in where statement found)

Um 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:

update TBLNAMES set NAME='Edited name' where ID=1;

Um eine Änderung an den Datenbank-Server zu senden, muss sqldb eine Aktualisierungsabfrage erstellen. Um diese Aktualisierungsabfrage zu erstellen, sind drei Dinge erforderlich:

Der Name der Tabelle
Der Tabellenname wird durch das Parsen (Durchsuchen, Analysieren) der SELECT-Abfrage ermittelt.
UPDATE oder INSERT Abschnitt
Dieser enthält die Felder, die geändert werden sollen.
WHERE Abschnitt
Dieser enthält die Felder, die bestimmen, welche Datensätze geändert werden sollen.

Jedes 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.

Welche 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.
Ist 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.

Der 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:

  • 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:
  Query.UsePrimaryKeyAsKey := True;
  • Setzen des Flags pfInKey für ein oder mehrere Felder im Code. Beispiel für einen zusammengesetzten Schlüssel:
  Query.FieldByName('Name').ProviderFlags := [pfInKey];
  Query.FieldByName('Vorname').ProviderFlags := [pfInKey];

Die UpdateMode Eigenschaft kennt zwei weitere mögliche Werte:

  • '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.
  • '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.


Wie führt man eine Abfrage unter der Verwendung von TSQLQuery aus?

Neben 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.
Die folgende Prozedur erzeugt eine Tabelle mittels TSQLQuery und fügt zwei Datensätze ein.

  procedure CreateTable;
  
  var Query : TSQLQuery;
  
  begin
    Query := GetQuery;
    Query.SQL.Text := 'create table TBLNAMES (ID integer, NAME varchar(40));';
    Query.ExecSQL;
  
    Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (1,'Name1');';
    Query.ExecSQL;
  
    Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (2,'Name2');';
    Query.ExecSQL;
  
    Query.Close;
    Query.Free;
  end;


Verwendung von Parametern in einer Abfrage

Im 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.

Die 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.
Zum Beispiel:

  Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';

Diese 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:

  Query.Params.ParamByName('Name').AsString := 'Name1';

Sie 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.

Das folgende Beispiel erzeugt die selbe Tabelle wie im vorherigen Beispiel, jetzt aber unter Verwendung von Parametern:

  procedure CreateTableUsingParameters;
  
  var Query : TSQLQuery;
      Param_ID,Param_Name: TParam; 
  
  begin
    Query := GetQuery;
    Query.SQL.Text := 'create table TBLNAMES (ID integer, NAME varchar(40));';
    Query.ExecSQL;
 
    Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
 
    Param_ID:=TParam.Create(Query.Params,ptInput);
    Param_ID.Name:='ID';
    Query.Params.AddParam(Param_ID);
 
    Param_Name:=TParam.Create(Query.Params,ptInput);
    Param_Name.Name:='Name';
    Query.Params.AddParam(Param_Name);
 
    Query.Params.ParamByName('ID').AsInteger := 1;
    Query.Params.ParamByName('NAME').AsString := 'Name1';
    Query.ExecSQL;
 
    Query.Params.ParamByName('ID').AsInteger := 2;
    Query.Params.ParamByName('NAME').AsString := 'Name2';
    Query.ExecSQL;
   
    Query.Close;
    Query.Free;
  end;

Was 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.
Mit '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.).
Beispiel für '.Prepare':

  for i := 1 to j do
  begin
    Query.paramByName('ID').AsInteger := i;
    Query.paramByName('Name').AsString := 'Name...';
    Query.Prepare;
    Query.ExecSQL;
  end;

Ein anderer Grund für die Verwendung von prepared statements ist die Vermeidung von SQL-Injection. Aber in manchen Fällen vereinfacht es auch nur die Programmierung.

Siehe auch

* Working_With_TSQLQuery.