Difference between revisions of "SqlDBHowto/fr"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(24 intermediate revisions by one other user not shown)
Line 5: Line 5:
 
Ce texte est conçu comme un 'comment-faire'. Je veux répondre à un nombre de question une par une, et expliquer comment vous pouvez utiliser les diverses classes. Toutes ces questions sont posées l'une après l'autre et forme une sorte de tutoriel.
 
Ce texte est conçu comme un 'comment-faire'. Je veux répondre à un nombre de question une par une, et expliquer comment vous pouvez utiliser les diverses classes. Toutes ces questions sont posées l'une après l'autre et forme une sorte de tutoriel.
  
Je vais essayer de le dire de telle façon que le texte peut être utilisé pour Lazarus ainsi que FreePascal. Cependant, les exemples sont pour FreePascal (c'est-à-dire qu'ils sont des applications de type console).
+
Je vais essayer de le dire de telle façon que le texte peut être utilisé pour Lazarus ainsi que FreePascal. Cependant, les exemples sont écrits pour FreePascal (c'est-à-dire qu'ils sont des applications de type console).
  
 
== Où puis-je trouver la documentation officielle ? ==
 
== Où puis-je trouver la documentation officielle ? ==
Line 24: Line 24:
 
* ODBC: [[TODBCConnection/fr|TODBCConnection]] (voir [[ODBCConn/fr#TODBCConnection]])
 
* ODBC: [[TODBCConnection/fr|TODBCConnection]] (voir [[ODBCConn/fr#TODBCConnection]])
 
* Oracle: [[TOracleConnection/fr|TOracleConnection]] (voir [[Oracle/fr|Oracle]])
 
* Oracle: [[TOracleConnection/fr|TOracleConnection]] (voir [[Oracle/fr|Oracle]])
* PostgreSQL: [[TPQConnection/fr|TPQConnection]] (voir [[postgresql/fr#SQLDB]])
+
* PostgreSQL: [[TPQConnection/fr|TPQConnection]] (voir [[postgres/fr#SQLDB]])
 
* Sqlite3: [[TSQLite3Connection/fr|TSQLite3Connection]] (disponible depuis  FPC version 2.2.2, voir [[SQLite/fr#Built-in_SQLDB]])  
 
* Sqlite3: [[TSQLite3Connection/fr|TSQLite3Connection]] (disponible depuis  FPC version 2.2.2, voir [[SQLite/fr#Built-in_SQLDB]])  
 
* Sybase ASE: [[TSybaseConnection/fr|TSybaseConnection]] (disponible depuis FPC 2.6.1, voir [[Lazarus_Database_Overview/fr#Lazarus_and_MSSQL.2FSybase|Lazarus et MSSQL/Sybase]])
 
* Sybase ASE: [[TSybaseConnection/fr|TSybaseConnection]] (disponible depuis FPC 2.6.1, voir [[Lazarus_Database_Overview/fr#Lazarus_and_MSSQL.2FSybase|Lazarus et MSSQL/Sybase]])
Line 37: Line 37:
 
Quand ces propriétés sont définies, vous pouvez créer une connection avec la méthode 'open'. Si la connection échoue, une exception EDatabaseError est levée. Utilisez la propriété 'connected' pour savoir si la connection a été établie avec le serveur de base données. Utilisez la méthode 'close' pour mettre fin à la connection avec le serveur.
 
Quand ces propriétés sont définies, vous pouvez créer une connection avec la méthode 'open'. Si la connection échoue, une exception EDatabaseError est levée. Utilisez la propriété 'connected' pour savoir si la connection a été établie avec le serveur de base données. Utilisez la méthode 'close' pour mettre fin à la connection avec le serveur.
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Program ConnectDB;
 
Program ConnectDB;
 +
 +
{$mode objfpc}{$H+}
 +
 +
uses
 +
  IBConnection;
 
   
 
   
 
function CreateConnection: TIBConnection;
 
function CreateConnection: TIBConnection;
Line 69: Line 74:
  
 
== Comment exécuter des requêtes directes/créer une base de données ? ==
 
== Comment exécuter des requêtes directes/créer une base de données ? ==
 +
SQlDB - le nom dit tout - fonctionne uniquement avec des serveurs de bases de données qui font usage de SQL. SQL signifie Langage Structuré de Requête (''Structured Query Language''), il est un langage développé pour permettre de travailler avec des bases de données relationnelles. Virtuellement chaque SGDBR (Système de Gestion de Bases de Données Relationnelles) a son propre dialecte, mais une grande partie des ordres SQL est la même pour tous les SGBDR.
  
SqlDB - the name says it all - only works with database server that make use of SQL. SQL stands for 'Structured Query Language' SQL is a language developed to allow working with relational databases. Virtually every database system has its own dialect, but a large number of SQL statements are the same for all database systems.
+
Dans FPC, il y a une différence entre :
 +
* des instructions qui retournent de l'information (un DataSet). Pour ceci, vous utiliserez un composant TSQLQuery ; voir [[#Comment lire de la donnée depuis une table ?]].
 +
* des instructions qui ne retournent pas d'information mais font quelque chose d'autre p.ex. mettre à jour des données. Pour ceci, vous pouvez aussi utiliser la méthode 'ExecuteDirect' de TSQLConnection (Vous pouvez également utiliser cette option si vous récupérez un jeu de données, mais que vous n'êtes pas intéressé par les résultats, par exemple dans une procédure stockée pouvant être sélectionnée).
  
In FPC, there is a difference between:
+
La plupart des SGBDR exécute des ordres SQL dans une transaction. Si vous voulez rendre les changements dans une transaction disponibles dans d'autres transactions, ou avoir ces changements disponibles après la fermeture de la transaction, alors vous devez faire un 'commit' de la transaction.
* SQL statements that return information (a dataset). For this, you have to use the TSQLQuery component; see [[#How to read data from a table?]].
 
* statements that do not return information but do something else, e.g. update data. For this, you may also use the 'ExecuteDirect' method of a TSQLConnection. (You can also use this if you get a dataset back but are not interested in the results, e.g. in a selectable stored procedure).
 
  
Most database system execute SQL statements within a transaction. 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.  
+
Pour supporter les transactions, SqlDB contient un composant TSQLTransaction. Un ordre SQL qui est exécuté par SqlDB doit toujours être exécuté au sein d'une transaction, même si le SGBDR ne supporte pas les transactions. Aussi, il y a des SGBD qui supporte la transaction et pour lequel TSQLConnection ne supporte pas (encore) la transaction. Même là, vous devez employer le composant TSQLTransaction.  
  
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 systems that do support transaction for which TSQLConnection does not (yet) support transaction. Even then, you must use the TSQLTransaction component.
+
Pour utiliser <tt>TSQLConnection.ExecuteDirect</tt> pour exécuter un ordre SQL, vous devez spécifier quelle 'transaction' doit être utilisée. A son tour, pour utiliser TSQLTransaction, vous devez spécifier quel
 +
composant TSQLConnection doit être utilisé.
  
To use <tt>TSQLConnection.ExecuteDirect</tt> to execute a SQL statement you must specify which 'Transaction' must be used. In turn, to use TSQLTransaction you must specify which TSQLConnection component must be used.
+
L'exemple suivant crée une table 'TBLNAMES' avec des champs 'NAME' et 'ID' et insère deux enregistrements. Cette fois en utilisant SQLite. Les ordres SQL employés ne sont pas expliqués. Pour plus d'information sur les ordres SQL, leur emploi et syntaxe, veuillez vous référer à la documentation du SGBDR. Remarquez que cet exemple ne tente pas d'intercepter les exceptions, ce qui est une mauvaise chose ! Regardez dans [https://www.freepascal.org/docs-html/current/ref/refch17.html#x226-24800017 Exceptions].
  
The following example creates a table 'TBLNAMES' with fields 'NAME' and 'ID' and inserts two records. The used SQL statements are not explained. For more information about the SQL statements, their use and syntax, please refer to the database system documentation. The procedure 'CreateConnection' is defined in the code example in [[#How to connect to a database server?]] above.
+
<syntaxhighlight lang=pascal>program CreateTable;
 
+
{$mode objfpc} {$ifdef mswindows}{$apptype console}{$endif}
<syntaxhighlight>program CreateTable;
+
uses
+
   sqldb, sqlite3conn;  
function CreateTransaction(pDB: TIBConnection): TSQLTransaction;
 
begin
 
   result := TSQLTransaction.Create(pDB);
 
  result.Database := pDB;
 
end;
 
 
   
 
   
 
var  
 
var  
   AConnection : TSQLConnection;
+
   AConnection : TSQLite3Connection;
 
   ATransaction : TSQLTransaction;
 
   ATransaction : TSQLTransaction;
 
+
 
begin
 
begin
   AConnection := CreateConnection;
+
   AConnection := TSQLite3Connection.Create(nil);
   ATransaction := CreateTransaction(AConnection);
+
  AConnection.DatabaseName := 'test_dbase';
 +
 +
   ATransaction := TSQLTransaction.Create(AConnection);
 
   AConnection.Transaction := ATransaction;
 
   AConnection.Transaction := ATransaction;
 
   AConnection.Open;
 
   AConnection.Open;
 
   ATransaction.StartTransaction;
 
   ATransaction.StartTransaction;
 
   AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));');  
 
   AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));');  
 
+
  // Some database-server types need a commit before you can use a newly created table. (Firebird)
+
   ATransaction.Commit;
  // With .Commit you also close the transaction
 
   ATransaction.Commit;  
 
 
   
 
   
 
   ATransaction.StartTransaction;
 
   ATransaction.StartTransaction;
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (1,'Name1');');  
+
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (1,''Name1'');');  
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (2,'Name2');');  
+
   AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (2,''Name2'');');  
 
   ATransaction.Commit;  
 
   ATransaction.Commit;  
 
   AConnection.Close;
 
   AConnection.Close;
 +
  ATransaction.Free;
 
   AConnection.Free;
 
   AConnection.Free;
  ATransaction.Free;
+
end</syntaxhighlight>
end.</syntaxhighlight>
 
  
 
== Comment lire de la donnée depuis une table ? ==
 
== Comment lire de la donnée depuis une table ? ==
Use the TSQLQuery component to read data from a table. A TSQLQuery component must be connected to a TSQLConnection component and a TSQLTransaction component to do its work. Setting the TSQLConnection and TSQLTransaction is discussed in [[#How to connect to a database server? ]] and [[#How to execute direct queries/make a table?]].  
+
Utilisez le composant TSQLQuery pour lire la donnée depuis une table. Un composant TSQLQuery doit être connecté à un composant TSQLConnection et à un composant TSQLTransaction pour réaliser sa tâche. La configuration de TSQLConnection et TSQLTransaction est discutée dans [[#Comment se connecter à un serveur de base de données ?]] et [[#Comment exécuter des requêtes directes/créer une base de données ?]].
 +
 
 +
Quand les TSQLConnection, TSQLTransaction et TSQLQuery sont connectés, alors TSQLQuery demande davantage de configuration pour fonctionner. TSQLQuery possède une propriété 'SQL' contenant un objet TStrings. La propriété TStrings contient un ordre SQL qui doit être exécuté. Si toutes les données de la table <tt>tablename</tt> doivent être lues, alors la propriété SQL doit contenir :
  
When the TSQLConnection, TSQLTransaction and TSQLQuery are connected, then TSQLQuery needs to be further configured to work.  TSQLQuery has a 'SQL' property containing a TStrings object. The 'SQL' property contains a SQL statement that must be executed. If all data from a table <tt>tablename</tt> must be read, then set the 'SQL' property to:
 
 
<syntaxhighlight lang="sql">'SELECT * FROM tablename;'</syntaxhighlight>.
 
<syntaxhighlight lang="sql">'SELECT * FROM tablename;'</syntaxhighlight>.
  
Use 'open' to read the table from the server and put the data in the TSQLQuery dataset. The data can be accessed through TSQLQuery until the query is closed using 'close'.
+
Utilisez 'Open' pour lire la table du serveur et mettre les données dans le DataSet TSQLQuery. La donnée peut être accédée à travers TSQLQuery jusqu'à ce que la requête soit fermée en utilisant 'Close'.
  
TSQLQuery is a subclass of TDataset. TDataset has a 'Fields' collection that contains all columns of the table. The TDataset also keeps track of the current record. Use 'First', 'Next', 'Prior' and 'Last' to change the current record. 'Bof' returns 'True' if the first record is reached, and 'Eof' returns 'True' if the last record is reached. To read the value of a field in the current record, first find the right 'TField' object and then use 'AsString', 'AsInteger', etc.
+
TSQLQuery est une sous-classe de TDataset. TDataset possède une collection de 'Fields' (champs) qui contiennent toutes les colonnes de la table. Le DataSet garde aussi la trace de l'enregistrement courant. Utilisez 'First', 'Next', 'Prior' et 'Last' pour changer l'enregistrement courant. 'Bof' retourne 'True' si le premier enregistrement est atteint et 'Eof' retourne 'True' si le dernier enregistrement est atteint. Pour lire la valeur d'un champ dans l'enregistrement courant, trouvez d'abord le bon objet 'TField' et alors utilisez 'AsString', AsInteger', etc.
  
 
=== Exemple : Lecture de donnée depuis une table ===
 
=== Exemple : Lecture de donnée depuis une table ===
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.
+
Ci-dessous se trouve un exemple qui affiche toutes les valeurs de la table tel que cela est fait au dessus [[#Comment exécuter des requêtes directes/créer une base de données ?]].
  
<syntaxhighlight>Program ShowData;
+
<syntaxhighlight lang=pascal>Program ShowData;
 
   
 
   
 
function CreateQuery(pConnection: TIBConnection; pTransaction: TSQLTransaction): TSQLQuery;
 
function CreateQuery(pConnection: TIBConnection; pTransaction: TSQLTransaction): TSQLQuery;
Line 164: Line 167:
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
  
(The code above of course is not quite finished, it misses 'try...finally' blocks. However, the above code intends to show the database code and thus the finishing touches are left out.)
+
(le code du dessus n'est bien sûr pas tout à fait terminé. Il manque des blocs 'try...finally'. Il s'agit de montrer le code d'accès à la base de données, la finition est mise de côté.)
Please note that 'TSQLTransaction.StartTransaction' is not used. This is not necessary. When TSQLQuery is opened, the SQL statement is executed and if no transaction is available then a transaction is automatically started. The programmer does not need to start the transaction explicitly.
+
Veuillez remarquer que 'TSQLTransaction.StartTransaction' n'est pas utilisé. Ce n'est pas nécessaire. Quand TSQLQuery est ouverte, l'ordre SQL est exécuté et si aucune transaction n'est disponible alors une transaction est automatiquement démarrée. Le développeur n'a pas besoin de démarrer une transaction explicitement.
The same applies for the connection maintained by TSQLConnection. The connection is opened as needed, the line 'Aconnection.Open' is not really required.
+
La même chose s'applique à la connection maintenue par TSQLConnection. La connection est ouverte au besoin, La ligne 'Aconnection.Open' n'est pas vraiment requise.
If a TSQLTransaction is destroyed, an automatic 'rollback' will be executed. '''Possible changes to data contained in the transaction will be lost.'''
+
Si un TSQLTransaction est détruit, un 'RollBack' automatique sera exécuté. '''Des modifications de données contenues dans la transaction pourront être perdues.'''
  
 
=== Pourquoi TSQLQuery.RecordCount retourne toujours 10 ? ===
 
=== Pourquoi TSQLQuery.RecordCount retourne toujours 10 ? ===
To count the records in a dataset, use '.RecordCount'. However, notice that '.RecordCount' shows the number of records that is already loaded from the server. For performance reasons, SqlDB does not read all records when opening TSQLQuery by default, only the first 10. Only when the eleventh record is accessed will the next set of 10 records be loaded, etc. Using '.Last', all records will be loaded.  
+
Pour compter les enregistrements dans un DataSet, utilisez la propriété  '.RecordCount'. Pourtant, remarquez que '.RecordCount' montre le nombre d'enregistrements qui sont déjà chargés depuis le serveur. Pour des raisons de performance, SqlDB ne lit pas tous les enregistrements à l'ouverture du TSQLQuery par défaut, seulement les 10 premiers. Ce n'est que lorsque le onzième enregistrement est accédé que le prochain ensemble de 10 enregistrements sera chargé, etc. En utilisant '.Last', tous les enregistrements seront chargés.
  
When you want to know the real number of records on the server you can first call '.Last' and then call '.RecordCount'.  
+
Quand vous voulez savoir le nombre effectif d'enregistrements sur le serveur, vous pouvez appeler '.Last' puis appeler '.RecordCount'.
  
An alternative is available. The number of records returned by the server is set by the '.PacketRecords' property. The default value is 10; if you make it -1 then all records will be loaded at once.
+
Une alternative est disponible. Le nombre d'enregistrements retourné par le serveur est définie par la propriété '.PacketRecords'. La valeur par défaut est 10, si vous la mettez à -1 alors tous les enregistrements seront chargés en une seule fois.
  
In current stable FPC, '.RecordCount' does not take filters into account, i.e. it shows the unfiltered total.
+
Dans la version stable actuelle de FPC, '.RecordCount' ne prend pas en considération les filtres, i.e. montre le total non filtré.
  
If you need the exact number of records, it often is a better idea to directly query the number of records in a query using another SQL query, but you would have to do that in the same transaction, as other transactions may have changed the number of records in the meanwhile.
+
Si vous avez besoin du nombre exact d'enregistrement, il est mieux de demander directement le nombre d'enregistrements dans une autre requête SQL, mais vous devez faire cela dans la même transaction, car d'autres transaction ont pu modifier ce nombre dans l'entre-temps.
  
 
=== Lazarus ===
 
=== Lazarus ===
Lazarus has various components to show data from a TDataset on a form. Instead of a While-loop and Writeln statements as used above, 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 the '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 used only in master-detail tables - see [[MasterDetail]]) Subsequently you may put a TDBGrid onto the form and set the 'Datasource' property of the grid to the TDatasource component you added before.
+
Lazarus possède divers composants pour montrer les données d'un DataSet sur une fiche. A la place d'une boucle while et d'appels WriteLn comme ci-dessus, vous pouvez utiliser des composants pour montrer les données dans une table. Placez les bons composant TSQLConnection, TSQLTransaction et TSQLQuery sur une fiche, connectez-les et configurez-les convenablement. En plus, vous aurez besoin d'un TDataSource ; mettez dans la propriété 'TDatasource.Dataset' le composant TSQLQuery que vous utilisez.
  
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.
+
('''Remarque''' ne définissez pas la propriété 'TSQLQuery.Datasource' par le composant TDatasource que vous utilisez. Cette propriété est réservée à la mise en place de realtion maître/détail entre tables - voir [[MasterDetail/fr|MasterDetail]]). Par la suite, vous pouvez poser un TDBGrid sur la fiche et définir la propriété 'DataSource' de la grille avec le composant TDataSource que vous avez ajouté auparavant.
 +
 
 +
Pour voir si tout marche, mettez à 'True' la propriété 'Connected' du TSQLConnection dans l'EDI de Lazarus. L'EDI tentera de se connecter au serveur de base de données immédiatement. Si cela marche, mettez à 'True' la proriété 'TSQLQuery.Active'. Si tout est bon, vous verrez - dans l'EDI - toutes les données de la table immédiatement à l'écran.
  
 
== Comment modifier de la donnée dans une table ? ==
 
== Comment modifier de la donnée dans une table ? ==
To change the data in a record, the [[TDataset]] (from which TSQLQuery is derived) must be set to edit mode. To enter edit mode call the '.Edit', '.Insert' or '.Append' methods. Use the '.Edit' method to change the current record. Use '.Insert' to insert a new record before the current record. Use '.Append' to insert a new record at the end of the table. In edit mode you can change field values through the 'Fields' property. 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. Use '.Cancel' to discard all changes you made since the last '.Post' call and leave the edit mode.
+
Pour modifier les données dans un enregistrement, les [[TDataSet/fr|TDataSet]] (duquel est dérivé TSQLQuery) doit être mis en mode édition. Pour ce faire, appelez l'une des méthodes '.Edit', '.Insert' ou '.Append'. Utilisez '.Edit' pour modifier les valeurs de l'enregistrement courant. Utilisez '.Insert' pour insérer un nouvel enregistrement avant l'enregistrement courant. Utilisez '.Append' pour ajouter un nouvel enregistrement en fin de la table. En mode Edit, vous pouvez changer les valeurs des champs grâce à la propriété 'Fields'. Utilisez la méthode '.Post' pour valider les nouvelles données, si les données sont valides, le mode Edit est abandonné. Si vous vous déplacez vers un autre enregistrement - par exemple en appelant '.Next' - et que le DataSet est en mode Edit, alors '.Post' est d'abord appelé. Utilisez '.Cancel' pour annuler tous les changements apportés depuis le dernier appel à '.Post' et quitter le mode Edit.
  
<syntaxhighlight>Query.Edit;
+
<syntaxhighlight lang=pascal>Query.Edit;
 
Query.FieldByName('NAME').AsString := 'Edited name';
 
Query.FieldByName('NAME').AsString := 'Edited name';
 
Query.Post;</syntaxhighlight>
 
Query.Post;</syntaxhighlight>
  
The above is not the complete story yet. TSQLQuery is derived from TBufDataset which makes use of buffered updates. Buffered update means 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. Only then will database server know of the changes. The changes are sent to the server within a transaction of TSQLTransaction. Make sure to properly set the transaction before 'ApplyUpdates'. After applying the updates, a commit must be executed to save the changes on the database server.
+
Ce qu'il y a au dessus n'est pas encore complet. TSQLQuery est dérivé de TBufDataset qui fait des mises à jour tamponnées (''buffered updates''). Les mises à jour tamponnées veulent dire qu'après l'appel à '.Post', les modifications sont visibles immédiatement dans l'ensemble de données mais pas envoyées au serveur de base de données. Il se passe que les modifications sont maintenues dans un journal des modifications. Quand la méthode '.ApplyUpdates' est appelée, tous les changements sont envoyés à la base de données. C'est à ce moment seulement que la base de données connaîtra les modifications. Les changements sont envoyés au serveur dans une transaction de TSQLTransaction. Assurez-vous de définir correctement la transaction avant d'appeler '.ApplyUpdates'. Après avoir appliquer les mises à jour, un commit doit être exécuté pour enregistrer les modifications sur le serveur de base de données.
  
The below is an example of changing the data in a table, sending the changes to the server and comitting the transaction.
+
Ci-dessous est un exemple de modification de données dans une table, d'envoi les modifications et de commit de la transaction.
  
<syntaxhighlight>Program EditData;
+
<syntaxhighlight lang=pascal>Program EditData;
 
   
 
   
 
var  
 
var  
Line 221: Line 226:
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
  
For a discussion of 'UpdateMode' continue reading.
+
Pour une discussion sur 'UpdateMode', continuer la lecture.
  
 
== Comment SqlDB envoie les modifications aux serveur de base de données ? ==
 
== Comment SqlDB envoie les modifications aux serveur de base de données ? ==
In the code example in [[#How to change data in a table?]], you will find the line
+
Dans l'exemple de code dans [[#Comment modifier de la donnée dans une table ?]], vous trouverez la ligne :
<syntaxhighlight>Query.UpdateMode := upWhereAll;</syntaxhighlight>
+
<syntaxhighlight lang=pascal>Query.UpdateMode := upWhereAll;</syntaxhighlight>
without explanation of what it does. The best way to find out what that line does is to leave it out. If you leave out the statement and the followed this howto precisely, then you will receive the following error message:
+
Sans explication de ce que cela fait. La meilleure façon de savoir ce que cette ligne fait est de la laisser de côté. Si vous laissez de côté l'instruction et suivez ce Comment-faire précisément, alors vous recevrez ce message d'erreur :
 
  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)
To understand what went wrong, you must understand how changes are sent to the database server. The only way to get data in a SQL server is by executing SQL queries. SQL has three types of queries for three different ways of manupulating a record. To create a new record, change or delete a record insert, update and delete statements are executed respectively. An update statement may be as follows:
+
Pour comprendre ce qui n'a pas marché, vous devez comprendre comment les modifications sont envoyées au serveur. La seule façon d'obtenir des données dans un serveur SQL est d'exécuter des requêtes. SQL a trois types de requêtes pour trois différentes façons de manipuler un enregistrement. Pour créer un nouvel enregistrement, modifier ou supprimer un enregistrement, les ordres insert, update et delete sont exécutés respectivement. Un ordre de mise à jour peut être comme ce qui suit :
 
<syntaxhighlight lang="sql">update TBLNAMES set NAME='Edited name' where ID=1;</syntaxhighlight>
 
<syntaxhighlight lang="sql">update TBLNAMES set NAME='Edited name' where ID=1;</syntaxhighlight>
To send a change to the database server, Sqldb must assemble an update query. To assemble the query, three things are needed:
+
Pour envoyer le changement au serveur de base de données, SqlDB doit assembler une requête update. Pour ce faire, trois choses sont nécessaires :  
; The name of the table : The table name is retrieved from parsing the select query, although this doesn't always work.  
+
; Le nom de la table : La nom de la table est récupéré par l'analyse de la requête de sélection, même si cela ne marche pas toujours.  
; <tt>UPDATE</tt> or <tt>INSERT</tt> clause : These contain the fields that must be changed.
+
; Clause <tt>UPDATE</tt> ou <tt>INSERT</tt> : Celle-ci contient les champs qui doivent être changés.
; <tt>WHERE</tt> clause : This contains the fields that determine which records should be changed.
+
; Clause <tt>WHERE</tt> : Celle-ci contient les champs qui détermine quels enregistrements devraient être changés.
 +
Chaque champ (chaque ''TField'' dans ''Fields'') possède une propriété ProviderFlags. Seuls les champs  avec '''pfInUpdate''' dans ''ProviderFlags'' seront utilisés dans la clause update ou insert d'une requête. Par défaut,  ''pfInUpdate''  est mis pour tous les champs dans leur proriété ''ProviderFlags''.
  
Every field (each ''TField'' in ''Fields'') has a ProviderFlags property. Only fields with '''pfInUpdate''' in ''ProviderFlags'' will be used in the update or insert cluase of a query. By default all fields have ''pfInUpdate'' set in their ''ProviderFlags'' property.
+
Le choix des champs utilisés dans la clause <tt>WHERE</tt> dépend de la propriété ''UpdateMode'' de la requête et de la propriété ''ProviderFlags'' des champs. Les champs avec ''pfInkey'' dans leur ''ProviderFlags'' sont toujours utilisés dans la clause <tt>WHERE</tt>. Un champ aura le drapeau ''pfInKey'' défini automatiquement si le champ fait partie de la clé primaire de la table et 'TSQLQuery.UsePrimaryKeyAsKey' retourne 'True'.
  
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'.
+
La valeur par défaut de ''UpdateMode'' de la requête est ''upWhereKeyOnly''. Dans le mode update, seuls les champs avec ''pfInkey'' dans leur propriété ''ProviderFlags'' sont utilisés dans la clause <tt>WHERE</tt>. Si aucun des champs n'a de drapeau ''pfInKey'' mis, alors aucun champ n'est disponible pour la clause <tt>WHERE</tt> et le message d'erreur du début de la section sera retourné. Vous pouvez résoudre ce problème en :
 +
* En ajoutant une clé primaire à la table et mettre ''TSQLQuery.UsePrimaryKeyAsKey'' à 'True', ou
 +
* en définissant le drapeau ''pfInkey'' pour un ou plusieurs champs dans le code.
  
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. You can solve the issue by:
+
La propriété '''UpdateMode''' connaît deux autres valeurs. 'upWhereAll' peut être utilisée pour ajouter tous les champs avec le drapeau 'pfInWhere' mis à la clause <tt>WHERE</tt>. Par défaut, tous les champs ont ce drapeau mis. 'upWhereChanged' peut être utilisé pour ceux des champs qui ont le drapeau 'pfInWhere' mis et dont la valeur a été changée dans l'enregistrement courant.
* Adding a primary key to the table and set ''TSQLQuery.UsePrimaryKeyAsKey'' to 'True', or
 
* Setting the ''pfInkey'' flag for one or more fields in code.
 
 
 
The '''UpdateMode''' property knows two more possible values. '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.
 
  
 
== Comment exécuter une requête en utilisant TSQLQuery ? ==
 
== Comment exécuter une requête en utilisant TSQLQuery ? ==
Next to statements that return a dataset (see [[#How to read data from a table?]]) SQL has statements that do not return data. For example <tt>INSERT</tt>, <tt>UPDATE</tt> and <tt>DELETE</tt> statements do not return data. These statements can be executed using ''[[#How to execute direct queries/make a table?|TSQLConnection.ExecuteDirect]]'', but TSQLQuery can also be used. If you do not expect return data use ''TSQLQuery.ExecSQL'' instead of ''TSQLQuery.Open''. As mentioned earlier, use ''TSQLQuery.Open'' to open the dataset returned by the SQL statement.  
+
À côté des instructions qui renvoient un DataSet (voir  [[#Comment lire de la donnée depuis une table ?]], SQL a des ordres qui ne retournent pas de donnée. P.ex., les ordres <tt>INSERT</tt>, <tt>UPDATE</tt> et <tt>DELETE</tt>. Ces ordres peuvent être exécutés en utilisant ''[[#Comment exécuter des requêtes directes/créer une base de données ?|TSQLConnection.ExecuteDirect]]'', mais TSQLQuery peut être aussi utilisé. Si vous n'attendez pas de donnée en retour, utilisez ''TSQLQuery.ExecSQL'' au lieu de ''TSQLQuery.Open''. Comme indiqué précédemment, utilisez ''TSQLQuery.Open'' pour ouvrir le DataSet retourné par l'ordre SQL.
  
The following procedure creates a table and inserts two records using TSQLQuery.
+
La procédure suivante crée une table et insère deux enregistrements en utilisant TSQLQuery.
  
<syntaxhighlight>procedure CreateTable;
+
<syntaxhighlight lang=pascal>procedure CreateTable;
 
    
 
    
 
var  
 
var  
Line 271: Line 275:
  
 
== Comment utiliser des paramètres dans une requête ? ==
 
== Comment utiliser des paramètres dans une requête ? ==
In the code example of [[#How to execute a query using TSQLQuery?]] the same query is used twice, only the values to be inserted differ. A better way to do this is by using parameters in the query.  
+
Dans l'exemple de code de [[#Comment exécuter une requête en utilisant TSQLQuery ?]], la même requête est utilisée deux fois, seules les valeurs à insérer diffèrent. Une meilleure façon pour faire cela consiste à utiliser des paramètres dans la requête.
 +
 
 +
La syntaxe des paramètres dans les requêtes est différente selon le SGBDR, mais les différences sont traitées par TSQLQuery. Remplacez les valeurs dans la requête avec un caractère deux-points suivi du nom du paramètre que vous voulez utiliser. Par exemples :
 +
<syntaxhighlight lang=pascal>Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';</syntaxhighlight>
  
The syntax of parameters in queries is different per database system, but the differences are handled by TSQLQuery. Replace the values in the query with a colon followed by the name of the parameter you want to use. For example:
+
Cette requête créera deux paramètres : 'ID' et 'NAME'.
<syntaxhighlight>Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';</syntaxhighlight>
+
Pour déterminer les paramètres, la requête est analysée au moment où le texte de ''TSQLQuery.SQL'' est affecté ou modifié. Tous les paramètres existants seront supprimés et les nouveaux paramètres seront ajoutés à la propriété 'TSQLQuery.Params'. L'affectation d'une valeur à un paramètre est similaire à l'affectation d'un champ dans un DataSet :
  
This query will create two parameters: 'ID' and 'NAME'.
+
<syntaxhighlight lang=pascal>Query.Params.ParamByName('Name').AsString := 'Name1';</syntaxhighlight>
To determine the parameters, the query is parsed at the moment the text of ''TSQLQuery.SQL'' is assigned or changed. All existing parameters will be removed and the new parameters will be added to the 'TSQLQuery.Params' property. Assigning a value to a parameter is similar to assigning a value to a field in the dataset:
 
<syntaxhighlight>Query.Params.ParamByName('Name').AsString := 'Name1';</syntaxhighlight>
 
  
You can't tell from the query what kind of data must be stored in the parameter. The data type of the parameter is determined at the moment a value is first assigned to the parameter. By assigning a value using '.AsString', the parameter is assigned the data type 'ftString'. You can determine the data type directly by setting the 'DataType' property. If an incorrect datatype is assigned to the parameter, then problems will occur during opening or executing the query.
+
Vous ne pouvez pas savoir depuis la requête quel type de donnée doit être stocké dans le paramètre. Le type de donnée est déterminé au moment où une valeur est en premier affectée à un paramètre. En affectant une valeur en utilisant '.AsString', le paramètre est affecté du type 'ftString'. Vous pouvez déterminer le type de donnée directement en définissant la propriété 'DataType'. Si un type de donnée incorrect est affecté au paramètre alors des problèmes surviendront lors de l'ouverture ou de l'exécution de la requête. Voir [[Database field type/fr|Type de champ de base de données]] pour plus d'information sur les types de donnée.
See [[Database field type]] for more information on data types.
 
  
 
=== Requête de sélection ===
 
=== Requête de sélection ===
An example of a select query with parameters would be to change something like this:
+
Un exemple de requête de sélection avec des paramètres changera quelque chose comme ceci :
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
   Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = '''+Edit1.Text+''' ORDER BY NAME ';
 
   Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = '''+Edit1.Text+''' ORDER BY NAME ';
 
</syntaxhighlight>
 
</syntaxhighlight>
to something like this:
+
en quelque chose comme cela :
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
   Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = :NAMEPARAM ORDER BY NAME ';
 
   Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = :NAMEPARAM ORDER BY NAME ';
 
   Query.Params.ParamByName('NAMEPARAM').AsString := Edit1.Text;
 
   Query.Params.ParamByName('NAMEPARAM').AsString := Edit1.Text;
Line 295: Line 299:
  
 
=== Exemple ===
 
=== Exemple ===
The following example creates the same table as the previous example, but now parameters are used:
+
L'exemple suivant crée la même table que l'exemple précédent, mais maintenant des paramètres sont utilisés :
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
procedure CreateTableUsingParameters;
 
procedure CreateTableUsingParameters;
 
    
 
    
Line 325: Line 329:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Notice that this example requires more code than the example without the parameters. Then what is the use of using parameters?  
+
Remarquez que cet exemple demande plus de code que l'exemple sans paramètre. Alors, à quoi sert l'utilisation de paramètres?
 
 
Speed is one of the reasons. The example with parameters is faster, because the database server parses the query only once (in the .Prepare statement or at first run).
 
  
Another reason to use prepared statements is prevention of [http://en.wikipedia.org/wiki/SQL_injection SQL-injection] (see also [[Secure programming]].  
+
La vitesse est une des raisons. L'exemple avec des paramètres est plus rapide, parce que le serveur de base de donnée analyse la requête une seule fois (dans l'instruction '.Prepare' ou à la première exécution).
 +
Une autre raison pour employer les instructions préparées est la prévention des [https://fr.wikipedia.org/wiki/Injection_SQL injections SQL] (voir aussi [[Secure programming/fr|Programmation sécurisée]]).
  
Finally, in some cases it just simplifies coding.
+
Finalement, dans certains cas, ils simplifient le codage.
  
== Dépannage : Connection par TSQLConnection ==
+
== Dépannage : Journalisation par TSQLConnection ==
You can let a TSQLConnection log what it is doing. This can be handy to see what your Lazarus program sends to the database exactly, to debug the database components themselves and perhaps to optimize your queries.
+
Vous pouvez laisser un journal TSQLConnection à ce qu'il fait. Cela peut être pratique pour voir ce que votre programme Lazarus envoie à la base de données exactement, pour déboguer les composants de base de données eux-mêmes et peut-être pour optimiser vos requêtes.<br/>
NB: if you use prepared statements/parametrized queries (see section above), the parameters are often sent in binary by the TSQLConnection descendent (e.g. TIBConnection), so you can't just copy/paste the logged SQL into a database query tool.
+
NB : Si vous utilisez des ordres préparés/requêtes paramétrées (vois la section du dessus), les paramètres sont souvent envoyées en binaire par le descendant de TSQLConnection (p.ex. TIBConnection), donc vous ne pouvez juste copier/coller le SQL journalisé dans un outil d'interrogation de la base de données. Indépendamment, la journalisation de la connection peut donner beaucoup d'indication sur ce que le programme fait.
Regardless, connection logging can give a lot of insight in what your program is doing.
 
  
Alternatives are:  
+
Les alternatives sont :  
# you can use the debugger to step through the database code if you have built FPC (and Lazarus) with debugging enabled.  
+
# vous pouvez utiliser le débogueur pour passer le code de base données si vous avez construit FPC (et Lazarus) avec le débogage activé.
# if you use ODBC drivers (at least on Windows) you could enable tracelog output in the ODBC control panel.
+
# si vous utilisez les pilotes ODBC (au moins sous Windows), vous pourrez activer la sortie tracelog depuis le panneau de contrôle ODBC.
# many databases allow you to monitor all statements sent to it from a certain IP address/connection.
+
# plusieurs SGBD vous permettent de contrôler tous les ordres envoyés vers lui depuis une adresse IP/une connection.
  
 
+
Si vous utilisez la jouranlisation TSQLConnection, deux choses sont requises :
If you use TSQLConnection logging, two things are required:
+
# indiquer quels sont les types d'événement que TSQLConnection doit journaliser.
# indicate which event types your TSQLConnection should log
+
# associer TSQLConnection à une fonction qui reçoit les événements et les traite (les enregistre dans un fichier, les affiche à l'écran, etc.).
# point TSQLConnection at a function that receives the events and processes them (logs them to file, prints them to screen, etc.).
+
Cette fonction doit être du type TDBLogNotifyEvent (voir sqldb.pp), donc elle doit avoir la signature :
That function must be of type TDBLogNotifyEvent (see sqldb.pp), so it needs this signature:
+
<syntaxhighlight lang=pascal>
<syntaxhighlight>
 
 
TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;
 
TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=== FPC (ou : la façon manuelle) ===
 
=== FPC (ou : la façon manuelle) ===
A code snippet can illustrate this:
+
Un extrait de code illustre ceci :
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
uses
 
uses
 
...
 
...
Line 400: Line 401:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
You can also use TSQLConnection's GlobalDBLogHook instead to log everything from multiple connections.
+
Vous pouvez aussi utiliser GlobalDBLogHook de TSQLConnection au lieu de journaliser depuis de multiples connections.
  
 
=== Lazarus (ou : la manière rapide) ===
 
=== Lazarus (ou : la manière rapide) ===
Finally, the description above is the FPC way of doing things as indicated in the introduction; if using Lazarus, a quicker way is to assign an event handler to the TSQLConnection's OnLog event.
+
Au final, la description du dessus est la manière FPC de procéder comme annoncé dans l'introduction ; si vous utilisez Lazarus, une façon plus rapide est d'affecter le gestionnaire d'événement dans l'événement OnLog de TSQLConnection.
 
 
[[Category:Databases]]
 
  
 
== Voir aussi ==
 
== Voir aussi ==
* [[Working With TSQLQuery]]
+
* [[SQLdb Tutorial0/fr|SQLdb Tutorial0]] : Instructions pour configurer les tables et les données d'exemple pour la série de tutoriels.
 +
* [[SQLdb Tutorial1/fr|SQLdb Tutorial1]] : 1re partie de la série de tutoriels sur les bases de données, montrant comment configurer un grid pour afficher les données.
 +
* [[SQLdb Tutorial2/fr|SQLdb Tutorial2]] : 2e partie de la série de tutoriels, montrant l'édition, l'insertion, etc.
 +
* [[SQLdb Tutorial3/fr|SQLdb Tutorial3]] : 3e partie de la série de tutoriels, montrant comment développer pour des bases de données multiples et utiliser une form de login.
 +
* [[SQLdb Tutorial4/fr|SQLdb Tutorial4]] : 4e partie de la série de tutoriels, montrant comment utiliser les data modules.
 +
* [[Lazarus Database Overview/fr|Vue d'ensemble des bases de données pour Lazarus]] : Information sur les bases de données supportées par Lazarus. Redirige vers des notes spécifiques à certaines bases de données.
 +
* [[SQLdb Package/fr|Paquet SQLdb]] : Information sur le paquetage SQLdb.
 +
* [[SQLdb Programming Reference/fr|Référence de programmation SQLdb]] : Une vue d'ensemble de l'interaction entre les composants de bases de données SQLdb.
 +
* [[SqlDBHowto/fr|SqlDBHowto]] : Information sur l'utilisation du paquet SQLdb.
 +
* [[Working With TSQLQuery/fr|Travailler avec TSQLQuery]] : Informations sur TSQLQuery.

Latest revision as of 13:10, 27 February 2020

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

Portail de la base de données

Références:

Tutoriels/articles pratiques :

Bases de données

Advantage - MySQL - MSSQL - Postgres - Interbase - Firebird - Oracle - ODBC - Paradox - SQLite - dBASE - MS Access - Zeos

Ce texte est conçu comme un 'comment-faire'. Je veux répondre à un nombre de question une par une, et expliquer comment vous pouvez utiliser les diverses classes. Toutes ces questions sont posées l'une après l'autre et forme une sorte de tutoriel.

Je vais essayer de le dire de telle façon que le texte peut être utilisé pour Lazarus ainsi que FreePascal. Cependant, les exemples sont écrits pour FreePascal (c'est-à-dire qu'ils sont des applications de type console).

Où puis-je trouver la documentation officielle ?

Veuillez voir la documentation officielle à la page SQLDB documentation.

Comment se connecter à un serveur de base de données ?

SqlDB ne se connecte pas directement à un serveur de base de données mais utilise un client qui correspond au serveur de base de données employé. SqlDB envoie les commandes à la bibliothèque cliente ; la bibliothèque cliente se connecte au serveur de base de données et transfert les commandes. Ce qui veut dire que la bibliothèque cliente doit être installée pour faire la connection à la base de données. Sous Windows le client est souvent une .dll, sous Linux un .so et sous OS/X une .dylib.

Quand la bibliothèque cliente est installée convenablement, vous pouvez vous connecter à la base de données en utilisant un composant TSQLConnection. Divers composants TSQLConnection sont disponibles pour les différents serveurs de bases de données (voir SQLdb_Package) :

Note pour MySQL - Il y a plusieurs différences entre les versions de clients qui font que les connections ne peuvent être interchangées. Si une bibliothèque cliente version 4.1 est installée, vous devez utiliser un TMySQL41Connection. Ce n'est pas lié au serveur MySQL ; en utilisant une bibliothèque cliente MySQL 4.1, vous pouvez probablement vous connecter à un serveur MySQL 5.0 (voir la documentation MySQL concernant les combinaisons supportées).

Bien que les détails diffèrent entre les les diverses bases de données, en général, vous aurez besoin de définir quatre propriétés pour vous connecter au serveur de base de données :

  • Le nom du serveur ou l'adresse IP
  • Le nom de la base de données
  • Le nom de connection
  • Le mot de passe

Quand ces propriétés sont définies, vous pouvez créer une connection avec la méthode 'open'. Si la connection échoue, une exception EDatabaseError est levée. Utilisez la propriété 'connected' pour savoir si la connection a été établie avec le serveur de base données. Utilisez la méthode 'close' pour mettre fin à la connection avec le serveur.

Program ConnectDB;
 
{$mode objfpc}{$H+}
 
uses
  IBConnection;
 
function CreateConnection: TIBConnection;
begin
  result := TIBConnection.Create(nil);
  result.Hostname := 'localhost';
  result.DatabaseName := '/opt/firebird/examples/employee.fdb';
  result.UserName := 'sysdba';
  result.Password := 'masterkey';
end;
 
var   
  AConnection : TIBConnection;

begin
  AConnection := CreateConnection;
  AConnection.Open;
  if Aconnection.Connected then
    writeln('Successful connect!')
  else
    writeln('This is not possible, because if the connection failed, ' +
            'an exception should be raised, so this code would not ' +
            'be executed');
  AConnection.Close;
  AConnection.Free;
end.

Si une exception est levée, lisez le message attentivement. Il se peut que le serveur ne soit pas en cours d'exécution, le nom de connection et/ou le mot de passe est incorrect ou le nom de base de données ou l'adresse IP sont mal orthographiés. Si le message d'erreur indique que la bibliothèque cliente n'est pas trouvée, alors il faut contrôler que le client est correctement installé. Souvent, le message d'erreur donne le nom du fichier recherché.

Comment exécuter des requêtes directes/créer une base de données ?

SQlDB - le nom dit tout - fonctionne uniquement avec des serveurs de bases de données qui font usage de SQL. SQL signifie Langage Structuré de Requête (Structured Query Language), il est un langage développé pour permettre de travailler avec des bases de données relationnelles. Virtuellement chaque SGDBR (Système de Gestion de Bases de Données Relationnelles) a son propre dialecte, mais une grande partie des ordres SQL est la même pour tous les SGBDR.

Dans FPC, il y a une différence entre :

  • des instructions qui retournent de l'information (un DataSet). Pour ceci, vous utiliserez un composant TSQLQuery ; voir #Comment lire de la donnée depuis une table ?.
  • des instructions qui ne retournent pas d'information mais font quelque chose d'autre p.ex. mettre à jour des données. Pour ceci, vous pouvez aussi utiliser la méthode 'ExecuteDirect' de TSQLConnection (Vous pouvez également utiliser cette option si vous récupérez un jeu de données, mais que vous n'êtes pas intéressé par les résultats, par exemple dans une procédure stockée pouvant être sélectionnée).

La plupart des SGBDR exécute des ordres SQL dans une transaction. Si vous voulez rendre les changements dans une transaction disponibles dans d'autres transactions, ou avoir ces changements disponibles après la fermeture de la transaction, alors vous devez faire un 'commit' de la transaction.

Pour supporter les transactions, SqlDB contient un composant TSQLTransaction. Un ordre SQL qui est exécuté par SqlDB doit toujours être exécuté au sein d'une transaction, même si le SGBDR ne supporte pas les transactions. Aussi, il y a des SGBD qui supporte la transaction et pour lequel TSQLConnection ne supporte pas (encore) la transaction. Même là, vous devez employer le composant TSQLTransaction.

Pour utiliser TSQLConnection.ExecuteDirect pour exécuter un ordre SQL, vous devez spécifier quelle 'transaction' doit être utilisée. A son tour, pour utiliser TSQLTransaction, vous devez spécifier quel composant TSQLConnection doit être utilisé.

L'exemple suivant crée une table 'TBLNAMES' avec des champs 'NAME' et 'ID' et insère deux enregistrements. Cette fois en utilisant SQLite. Les ordres SQL employés ne sont pas expliqués. Pour plus d'information sur les ordres SQL, leur emploi et syntaxe, veuillez vous référer à la documentation du SGBDR. Remarquez que cet exemple ne tente pas d'intercepter les exceptions, ce qui est une mauvaise chose ! Regardez dans Exceptions.

program CreateTable;
{$mode objfpc} {$ifdef mswindows}{$apptype console}{$endif}
uses
  sqldb, sqlite3conn; 
 
var 
  AConnection : TSQLite3Connection;
  ATransaction : TSQLTransaction;
 
begin
  AConnection := TSQLite3Connection.Create(nil);
  AConnection.DatabaseName := 'test_dbase';
 
  ATransaction := TSQLTransaction.Create(AConnection);
  AConnection.Transaction := ATransaction;
  AConnection.Open;
  ATransaction.StartTransaction;
  AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));'); 
 
  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;
  ATransaction.Free;	
  AConnection.Free;
end

Comment lire de la donnée depuis une table ?

Utilisez le composant TSQLQuery pour lire la donnée depuis une table. Un composant TSQLQuery doit être connecté à un composant TSQLConnection et à un composant TSQLTransaction pour réaliser sa tâche. La configuration de TSQLConnection et TSQLTransaction est discutée dans #Comment se connecter à un serveur de base de données ? et #Comment exécuter des requêtes directes/créer une base de données ?.

Quand les TSQLConnection, TSQLTransaction et TSQLQuery sont connectés, alors TSQLQuery demande davantage de configuration pour fonctionner. TSQLQuery possède une propriété 'SQL' contenant un objet TStrings. La propriété TStrings contient un ordre SQL qui doit être exécuté. Si toutes les données de la table tablename doivent être lues, alors la propriété SQL doit contenir :

'SELECT * FROM tablename;'

.

Utilisez 'Open' pour lire la table du serveur et mettre les données dans le DataSet TSQLQuery. La donnée peut être accédée à travers TSQLQuery jusqu'à ce que la requête soit fermée en utilisant 'Close'.

TSQLQuery est une sous-classe de TDataset. TDataset possède une collection de 'Fields' (champs) qui contiennent toutes les colonnes de la table. Le DataSet garde aussi la trace de l'enregistrement courant. Utilisez 'First', 'Next', 'Prior' et 'Last' pour changer l'enregistrement courant. 'Bof' retourne 'True' si le premier enregistrement est atteint et 'Eof' retourne 'True' si le dernier enregistrement est atteint. Pour lire la valeur d'un champ dans l'enregistrement courant, trouvez d'abord le bon objet 'TField' et alors utilisez 'AsString', AsInteger', etc.

Exemple : Lecture de donnée depuis une table

Ci-dessous se trouve un exemple qui affiche toutes les valeurs de la table tel que cela est fait au dessus #Comment exécuter des requêtes directes/créer une base de données ?.

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

(le code du dessus n'est bien sûr pas tout à fait terminé. Il manque des blocs 'try...finally'. Il s'agit de montrer le code d'accès à la base de données, la finition est mise de côté.) Veuillez remarquer que 'TSQLTransaction.StartTransaction' n'est pas utilisé. Ce n'est pas nécessaire. Quand TSQLQuery est ouverte, l'ordre SQL est exécuté et si aucune transaction n'est disponible alors une transaction est automatiquement démarrée. Le développeur n'a pas besoin de démarrer une transaction explicitement. La même chose s'applique à la connection maintenue par TSQLConnection. La connection est ouverte au besoin, La ligne 'Aconnection.Open' n'est pas vraiment requise. Si un TSQLTransaction est détruit, un 'RollBack' automatique sera exécuté. Des modifications de données contenues dans la transaction pourront être perdues.

Pourquoi TSQLQuery.RecordCount retourne toujours 10 ?

Pour compter les enregistrements dans un DataSet, utilisez la propriété '.RecordCount'. Pourtant, remarquez que '.RecordCount' montre le nombre d'enregistrements qui sont déjà chargés depuis le serveur. Pour des raisons de performance, SqlDB ne lit pas tous les enregistrements à l'ouverture du TSQLQuery par défaut, seulement les 10 premiers. Ce n'est que lorsque le onzième enregistrement est accédé que le prochain ensemble de 10 enregistrements sera chargé, etc. En utilisant '.Last', tous les enregistrements seront chargés.

Quand vous voulez savoir le nombre effectif d'enregistrements sur le serveur, vous pouvez appeler '.Last' puis appeler '.RecordCount'.

Une alternative est disponible. Le nombre d'enregistrements retourné par le serveur est définie par la propriété '.PacketRecords'. La valeur par défaut est 10, si vous la mettez à -1 alors tous les enregistrements seront chargés en une seule fois.

Dans la version stable actuelle de FPC, '.RecordCount' ne prend pas en considération les filtres, i.e. montre le total non filtré.

Si vous avez besoin du nombre exact d'enregistrement, il est mieux de demander directement le nombre d'enregistrements dans une autre requête SQL, mais vous devez faire cela dans la même transaction, car d'autres transaction ont pu modifier ce nombre dans l'entre-temps.

Lazarus

Lazarus possède divers composants pour montrer les données d'un DataSet sur une fiche. A la place d'une boucle while et d'appels WriteLn comme ci-dessus, vous pouvez utiliser des composants pour montrer les données dans une table. Placez les bons composant TSQLConnection, TSQLTransaction et TSQLQuery sur une fiche, connectez-les et configurez-les convenablement. En plus, vous aurez besoin d'un TDataSource ; mettez dans la propriété 'TDatasource.Dataset' le composant TSQLQuery que vous utilisez.

(Remarque ne définissez pas la propriété 'TSQLQuery.Datasource' par le composant TDatasource que vous utilisez. Cette propriété est réservée à la mise en place de realtion maître/détail entre tables - voir MasterDetail). Par la suite, vous pouvez poser un TDBGrid sur la fiche et définir la propriété 'DataSource' de la grille avec le composant TDataSource que vous avez ajouté auparavant.

Pour voir si tout marche, mettez à 'True' la propriété 'Connected' du TSQLConnection dans l'EDI de Lazarus. L'EDI tentera de se connecter au serveur de base de données immédiatement. Si cela marche, mettez à 'True' la proriété 'TSQLQuery.Active'. Si tout est bon, vous verrez - dans l'EDI - toutes les données de la table immédiatement à l'écran.

Comment modifier de la donnée dans une table ?

Pour modifier les données dans un enregistrement, les TDataSet (duquel est dérivé TSQLQuery) doit être mis en mode édition. Pour ce faire, appelez l'une des méthodes '.Edit', '.Insert' ou '.Append'. Utilisez '.Edit' pour modifier les valeurs de l'enregistrement courant. Utilisez '.Insert' pour insérer un nouvel enregistrement avant l'enregistrement courant. Utilisez '.Append' pour ajouter un nouvel enregistrement en fin de la table. En mode Edit, vous pouvez changer les valeurs des champs grâce à la propriété 'Fields'. Utilisez la méthode '.Post' pour valider les nouvelles données, si les données sont valides, le mode Edit est abandonné. Si vous vous déplacez vers un autre enregistrement - par exemple en appelant '.Next' - et que le DataSet est en mode Edit, alors '.Post' est d'abord appelé. Utilisez '.Cancel' pour annuler tous les changements apportés depuis le dernier appel à '.Post' et quitter le mode Edit.

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

Ce qu'il y a au dessus n'est pas encore complet. TSQLQuery est dérivé de TBufDataset qui fait des mises à jour tamponnées (buffered updates). Les mises à jour tamponnées veulent dire qu'après l'appel à '.Post', les modifications sont visibles immédiatement dans l'ensemble de données mais pas envoyées au serveur de base de données. Il se passe que les modifications sont maintenues dans un journal des modifications. Quand la méthode '.ApplyUpdates' est appelée, tous les changements sont envoyés à la base de données. C'est à ce moment seulement que la base de données connaîtra les modifications. Les changements sont envoyés au serveur dans une transaction de TSQLTransaction. Assurez-vous de définir correctement la transaction avant d'appeler '.ApplyUpdates'. Après avoir appliquer les mises à jour, un commit doit être exécuté pour enregistrer les modifications sur le serveur de base de données.

Ci-dessous est un exemple de modification de données dans une table, d'envoi les modifications et de commit de la transaction.

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

Pour une discussion sur 'UpdateMode', continuer la lecture.

Comment SqlDB envoie les modifications aux serveur de base de données ?

Dans l'exemple de code dans #Comment modifier de la donnée dans une table ?, vous trouverez la ligne :

Query.UpdateMode := upWhereAll;

Sans explication de ce que cela fait. La meilleure façon de savoir ce que cette ligne fait est de la laisser de côté. Si vous laissez de côté l'instruction et suivez ce Comment-faire précisément, alors vous recevrez ce message d'erreur :

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

Pour comprendre ce qui n'a pas marché, vous devez comprendre comment les modifications sont envoyées au serveur. La seule façon d'obtenir des données dans un serveur SQL est d'exécuter des requêtes. SQL a trois types de requêtes pour trois différentes façons de manipuler un enregistrement. Pour créer un nouvel enregistrement, modifier ou supprimer un enregistrement, les ordres insert, update et delete sont exécutés respectivement. Un ordre de mise à jour peut être comme ce qui suit :

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

Pour envoyer le changement au serveur de base de données, SqlDB doit assembler une requête update. Pour ce faire, trois choses sont nécessaires :

Le nom de la table
La nom de la table est récupéré par l'analyse de la requête de sélection, même si cela ne marche pas toujours.
Clause UPDATE ou INSERT
Celle-ci contient les champs qui doivent être changés.
Clause WHERE
Celle-ci contient les champs qui détermine quels enregistrements devraient être changés.

Chaque champ (chaque TField dans Fields) possède une propriété ProviderFlags. Seuls les champs avec pfInUpdate dans ProviderFlags seront utilisés dans la clause update ou insert d'une requête. Par défaut, pfInUpdate est mis pour tous les champs dans leur proriété ProviderFlags.

Le choix des champs utilisés dans la clause WHERE dépend de la propriété UpdateMode de la requête et de la propriété ProviderFlags des champs. Les champs avec pfInkey dans leur ProviderFlags sont toujours utilisés dans la clause WHERE. Un champ aura le drapeau pfInKey défini automatiquement si le champ fait partie de la clé primaire de la table et 'TSQLQuery.UsePrimaryKeyAsKey' retourne 'True'.

La valeur par défaut de UpdateMode de la requête est upWhereKeyOnly. Dans le mode update, seuls les champs avec pfInkey dans leur propriété ProviderFlags sont utilisés dans la clause WHERE. Si aucun des champs n'a de drapeau pfInKey mis, alors aucun champ n'est disponible pour la clause WHERE et le message d'erreur du début de la section sera retourné. Vous pouvez résoudre ce problème en :

  • En ajoutant une clé primaire à la table et mettre TSQLQuery.UsePrimaryKeyAsKey à 'True', ou
  • en définissant le drapeau pfInkey pour un ou plusieurs champs dans le code.

La propriété UpdateMode connaît deux autres valeurs. 'upWhereAll' peut être utilisée pour ajouter tous les champs avec le drapeau 'pfInWhere' mis à la clause WHERE. Par défaut, tous les champs ont ce drapeau mis. 'upWhereChanged' peut être utilisé pour ceux des champs qui ont le drapeau 'pfInWhere' mis et dont la valeur a été changée dans l'enregistrement courant.

Comment exécuter une requête en utilisant TSQLQuery ?

À côté des instructions qui renvoient un DataSet (voir #Comment lire de la donnée depuis une table ?, SQL a des ordres qui ne retournent pas de donnée. P.ex., les ordres INSERT, UPDATE et DELETE. Ces ordres peuvent être exécutés en utilisant TSQLConnection.ExecuteDirect, mais TSQLQuery peut être aussi utilisé. Si vous n'attendez pas de donnée en retour, utilisez TSQLQuery.ExecSQL au lieu de TSQLQuery.Open. Comme indiqué précédemment, utilisez TSQLQuery.Open pour ouvrir le DataSet retourné par l'ordre SQL.

La procédure suivante crée une table et insère deux enregistrements en utilisant TSQLQuery.

procedure CreateTable;
  
var 
  Query : TSQLQuery;
  
begin
  Query := CreateQuery(AConnection, ATransaction);
  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;

Comment utiliser des paramètres dans une requête ?

Dans l'exemple de code de #Comment exécuter une requête en utilisant TSQLQuery ?, la même requête est utilisée deux fois, seules les valeurs à insérer diffèrent. Une meilleure façon pour faire cela consiste à utiliser des paramètres dans la requête.

La syntaxe des paramètres dans les requêtes est différente selon le SGBDR, mais les différences sont traitées par TSQLQuery. Remplacez les valeurs dans la requête avec un caractère deux-points suivi du nom du paramètre que vous voulez utiliser. Par exemples :

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

Cette requête créera deux paramètres : 'ID' et 'NAME'. Pour déterminer les paramètres, la requête est analysée au moment où le texte de TSQLQuery.SQL est affecté ou modifié. Tous les paramètres existants seront supprimés et les nouveaux paramètres seront ajoutés à la propriété 'TSQLQuery.Params'. L'affectation d'une valeur à un paramètre est similaire à l'affectation d'un champ dans un DataSet :

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

Vous ne pouvez pas savoir depuis la requête quel type de donnée doit être stocké dans le paramètre. Le type de donnée est déterminé au moment où une valeur est en premier affectée à un paramètre. En affectant une valeur en utilisant '.AsString', le paramètre est affecté du type 'ftString'. Vous pouvez déterminer le type de donnée directement en définissant la propriété 'DataType'. Si un type de donnée incorrect est affecté au paramètre alors des problèmes surviendront lors de l'ouverture ou de l'exécution de la requête. Voir Type de champ de base de données pour plus d'information sur les types de donnée.

Requête de sélection

Un exemple de requête de sélection avec des paramètres changera quelque chose comme ceci :

  Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = '''+Edit1.Text+''' ORDER BY NAME ';

en quelque chose comme cela :

  Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = :NAMEPARAM ORDER BY NAME ';
  Query.Params.ParamByName('NAMEPARAM').AsString := Edit1.Text;

Exemple

L'exemple suivant crée la même table que l'exemple précédent, mais maintenant des paramètres sont utilisés :

procedure CreateTableUsingParameters;
  
var 
  Query : TSQLQuery;
  
begin
  Query := CreateQuery(AConnection, ATransaction);
  Query.SQL.Text := 'create table TBLNAMES (ID integer, NAME varchar(40));';
  Query.ExecSQL;

  Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);';
  Query.Prepare;
  
  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.UnPrepare; // no need to call this; should be called by Query.Close
  Query.Close;
  Query.Free;
end;

Remarquez que cet exemple demande plus de code que l'exemple sans paramètre. Alors, à quoi sert l'utilisation de paramètres?

La vitesse est une des raisons. L'exemple avec des paramètres est plus rapide, parce que le serveur de base de donnée analyse la requête une seule fois (dans l'instruction '.Prepare' ou à la première exécution). Une autre raison pour employer les instructions préparées est la prévention des injections SQL (voir aussi Programmation sécurisée).

Finalement, dans certains cas, ils simplifient le codage.

Dépannage : Journalisation par TSQLConnection

Vous pouvez laisser un journal TSQLConnection à ce qu'il fait. Cela peut être pratique pour voir ce que votre programme Lazarus envoie à la base de données exactement, pour déboguer les composants de base de données eux-mêmes et peut-être pour optimiser vos requêtes.
NB : Si vous utilisez des ordres préparés/requêtes paramétrées (vois la section du dessus), les paramètres sont souvent envoyées en binaire par le descendant de TSQLConnection (p.ex. TIBConnection), donc vous ne pouvez juste copier/coller le SQL journalisé dans un outil d'interrogation de la base de données. Indépendamment, la journalisation de la connection peut donner beaucoup d'indication sur ce que le programme fait.

Les alternatives sont :

  1. vous pouvez utiliser le débogueur pour passer le code de base données si vous avez construit FPC (et Lazarus) avec le débogage activé.
  2. si vous utilisez les pilotes ODBC (au moins sous Windows), vous pourrez activer la sortie tracelog depuis le panneau de contrôle ODBC.
  3. plusieurs SGBD vous permettent de contrôler tous les ordres envoyés vers lui depuis une adresse IP/une connection.

Si vous utilisez la jouranlisation TSQLConnection, deux choses sont requises :

  1. indiquer quels sont les types d'événement que TSQLConnection doit journaliser.
  2. associer TSQLConnection à une fonction qui reçoit les événements et les traite (les enregistre dans un fichier, les affiche à l'écran, etc.).

Cette fonction doit être du type TDBLogNotifyEvent (voir sqldb.pp), donc elle doit avoir la signature :

TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;

FPC (ou : la façon manuelle)

Un extrait de code illustre ceci :

uses
...
TSQLConnection, //or a child object like TIBConnection, TMSSQLConnection
...
var
type 
  TMyApplication = class(TCustomApplication); //this is our application that uses the connection
...
  private
    // This example stores the logged events in this stringlist:
    FConnectionLog: TStringList;
...
  protected
    // This procedure will receive the events that are logged by the connection:
    procedure GetLogEvent(Sender: TSQLConnection; EventType: TDBEventType; Const Msg : String);
...
  procedure TMyApplication.GetLogEvent(Sender: TSQLConnection;
    EventType: TDBEventType; const Msg: String);
  // The procedure is called by TSQLConnection and saves the received log messages
  // in the FConnectionLog stringlist
  var
    Source: string;
  begin
    // Nicely right aligned...
    case EventType of
      detCustom:   Source:='Custom:  ';
      detPrepare:  Source:='Prepare: ';
      detExecute:  Source:='Execute: ';
      detFetch:    Source:='Fetch:   ';
      detCommit:   Source:='Commit:  ';
      detRollBack: Source:='Rollback:';
      else Source:='Unknown event. Please fix program code.';
    end;
    FConnectionLog.Add(Source + ' ' + Msg);
  end;

...
  // We do need to tell our TSQLConnection what to log:
    FConnection.LogEvents:=LogAllEvents; //= [detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack]
    // ... and to which procedure the connection should send the events:
    FConnection.OnLog:=@Self.GetLogEvent;
...
  // now we can use the connection and the FConnectionLog stringlist will fill with log messages.

Vous pouvez aussi utiliser GlobalDBLogHook de TSQLConnection au lieu de journaliser depuis de multiples connections.

Lazarus (ou : la manière rapide)

Au final, la description du dessus est la manière FPC de procéder comme annoncé dans l'introduction ; si vous utilisez Lazarus, une façon plus rapide est d'affecter le gestionnaire d'événement dans l'événement OnLog de TSQLConnection.

Voir aussi

  • SQLdb Tutorial0 : Instructions pour configurer les tables et les données d'exemple pour la série de tutoriels.
  • SQLdb Tutorial1 : 1re partie de la série de tutoriels sur les bases de données, montrant comment configurer un grid pour afficher les données.
  • SQLdb Tutorial2 : 2e partie de la série de tutoriels, montrant l'édition, l'insertion, etc.
  • SQLdb Tutorial3 : 3e partie de la série de tutoriels, montrant comment développer pour des bases de données multiples et utiliser une form de login.
  • SQLdb Tutorial4 : 4e partie de la série de tutoriels, montrant comment utiliser les data modules.
  • Vue d'ensemble des bases de données pour Lazarus : Information sur les bases de données supportées par Lazarus. Redirige vers des notes spécifiques à certaines bases de données.
  • Paquet SQLdb : Information sur le paquetage SQLdb.
  • Référence de programmation SQLdb : Une vue d'ensemble de l'interaction entre les composants de bases de données SQLdb.
  • SqlDBHowto : Information sur l'utilisation du paquet SQLdb.
  • Travailler avec TSQLQuery : Informations sur TSQLQuery.