Sign in Join
Wiki copytemporary

SQLdb Tutorial2/fr: what changed

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

OldNewLine
1+---
2+[[Portal:Databases|**Portail de la base de données**]]
3+Références: · [[Databases/fr|Information générale]] · [[Database libraries/fr|Bibliothèques]] · [[Database field type/fr|Types de champ]] · [[Data Controls tab/fr|Contrôles]] · [[Lazarus DB Faq/fr|FAQ]] · [[SqlDBHowto/fr|Comment faire en SQL ?]] · [[Working With TSQLQuery/fr|Travailler avec TSQLQuery]] · [[How to write in-memory database applications in Lazarus/FPC/fr|Applications de base de données en mémoire]] · Tutoriels/articles pratiques : · [[Lazarus Database Overview/fr|Vue d'ensemble]] · [[SQLdb Tutorial0/fr|0 - Configuration de la base de données]] · [[SQLdb Tutorial1/fr|1 - Commençons]] · 2 - Edition · [[SQLdb Tutorial3/fr|3 - Requêtes]] · [[SQLdb Tutorial4/fr|4 - Modules de données]] · [[SQLdb Programming Reference/fr|Référence de programmation SQLdb]] · Bases de données · [[Advantage Database Server/fr|Advantage]] \- [[MySQLDatabases/fr|MySQL]] \- [[mssqlconn/fr|MSSQL]] \- [[postgres/fr|Postgres]] \- [[Firebird/fr|Interbase]] \- [[Firebird/fr|Firebird]] \- [[Oracle/fr|Oracle]] \- [[ODBCConn/fr|ODBC]] \- [[TParadox/fr|Paradox]] \- [[SQLite/fr|SQLite]] \- [[Lazarus Tdbf Tutorial/fr|dBASE]] \- [[MS Access/fr|MS Access]] \- [[Zeos tutorial/fr|Zeos]]
4+
5+
16## Vue d'ensemble
27
3-Si vous avez suivi le [[SQLdb Tutorial1/fr|Tutoriel SQLdb 1]], vous avez un grille basique montrant des informations provenant de la base de données. Maintenant que votre application marche, vous pouvez y ajouter certains raffinements.
8+Si vous avez suivi le [[SQLdb Tutorial1/fr|Tutoriel SQLdb 1]], vous avez un grille basique montrant des informations provenant de la base de données. Maintenant que votre application marche, vous pouvez y ajouter certains raffinements.
49
510### Connexion dynamique à une base de données
611
7-Jusqu'à maintenant, nous utilisions des nom de base de données, emplacement de base de données, nom d'utilisateur et mot de passe fixé pour simplifier. Comme indiqué, des applications "réelles" laissent normalement les utilisateurs spécifier leur propres nom d'utilisateur et mot de passe.
8-
9-Changeons la fiche de façon à pouvoir les spécifier : ajoutez deux [[TEdit/fr|TEdits]] depuis l'onglet standard. Mettez leur propriété Name à 'Username' et 'Password'. Définissez la propriété PasswordChar de 'Password' à * (l'astérisque) par sécurité vis à vis de personne qui regarderait par dessus votre épaule.
12+Jusqu'à maintenant, nous utilisions des nom de base de données, emplacement de base de données, nom d'utilisateur et mot de passe fixé pour simplifier. Comme indiqué, des applications "réelles" laissent normalement les utilisateurs spécifier leur propres nom d'utilisateur et mot de passe.
1013
11-Si vous voulez rendre plus facile (et moins sécurisé, bien sûr) de se connecter, vous pouvez définir la propriété Text de UserName avec un nom d'utilisateur valide de la base de données, tel que SYSDBA. Vous pouvez même définir la propriété Text de Password à une valeur par défaut telle que masterkey, simple pour le test sur une machine de développement si la sécurité n'est pas une préoccupation...
14+Changeons la fiche de façon à pouvoir les spécifier : ajoutez deux [[TEdit/fr|TEdits]] depuis l'onglet standard. Mettez leur propriété Name à 'Username' et 'Password'. Définissez la propriété PasswordChar de 'Password' à * (l'astérisque) par sécurité vis à vis de personne qui regarderait par dessus votre épaule.
1215
13-Cosmétiquement, l'ajout de quelques étiquettes (*Label*) pour que les gens sachent ce qu'ils sont censés taper est utile.
16+Si vous voulez rendre plus facile (et moins sécurisé, bien sûr) de se connecter, vous pouvez définir la propriété Text de UserName avec un nom d'utilisateur valide de la base de données, tel que SYSDBA. Vous pouvez même définir la propriété Text de Password à une valeur par défaut telle que masterkey, simple pour le test sur une machine de développement si la sécurité n'est pas une préoccupation...
1417
15-Aussi pour rendre plus facile la connexion à toute base de données exemple sur tout serveur Firebird/Interbase, nous ajoutons deux zone de texte pour le serveur et le chemin à la base de données. Ajoutons ces deux autres zones de texte et appelons-les ServerName et DatabaseName.
18+Cosmétiquement, l'ajout de quelques étiquettes (_Label_) pour que les gens sachent ce qu'ils sont censés taper est utile.
1619
17-Si vous voulez, vous pouvez définir la propriété 'Text' à des valeurs sensibles dans votre situation, p.ex. localhost et `C:\Program Files\Firebird\Firebird_2_5\examples\empbuild\EMPLOYEE.FDB`. Des étiquettes (*Labels*) pour expliquer ce que doit entrer l'utilisateur peuvent aider aussi.
20+Aussi pour rendre plus facile la connexion à toute base de données exemple sur tout serveur Firebird/Interbase, nous ajoutons deux zone de texte pour le serveur et le chemin à la base de données. Ajoutons ces deux autres zones de texte et appelons-les ServerName et DatabaseName.
1821
19-Pour clarifier, nous allons supprimer les informations de connexion de nos composants en conception : Dans le composant [[TSQLConnector/fr|TSQLConnector]], retirez tout les textes des propriétés UserName, Password, DatabaseName et HostName.
22+Si vous voulez, vous pouvez définir la propriété 'Text' à des valeurs sensibles dans votre situation, p.ex. localhost et `C:\Program Files\Firebird\Firebird_2_5\examples\empbuild\EMPLOYEE.FDB`. Des étiquettes (_Labels_) pour expliquer ce que doit entrer l'utilisateur peuvent aider aussi.
2023
21-Maintenant, finalement, nous avons besoin d'indiquer à notre composant de connexion à la base de données comment se connecter. Cela est uniquement nécessaire au début de l'exécution de l'application. Dans notre cas, le bouton existant 'Button1' est une bonne manière de mettre en place la connexion.
24+Pour clarifier, nous allons supprimer les informations de connexion de nos composants en conception : Dans le composant [[TSQLConnector/fr|TSQLConnector]], retirez tout les textes des propriétés UserName, Password, DatabaseName et HostName.
2225
23-Ajoutez le code :
26+Maintenant, finalement, nous avons besoin d'indiquer à notre composant de connexion à la base de données comment se connecter. Cela est uniquement nécessaire au début de l'exécution de l'application. Dans notre cas, le bouton existant 'Button1' est une bonne manière de mettre en place la connexion.
2427
25-``` pascal
28+Ajoutez le code :
29+```
2630procedure TForm1.Button1Click(Sender: TObject);
27-begin
28- SQLQuery1.Close;
29- //Connection settings for Firebird/Interbase database
30- //only needed when we have not yet connected:
31- if not DBConnection.Connected then
32- begin
33- DBConnection.HostName := ServerName.Text;
34- DBConnection.DatabaseName := DatabaseName.Text;
35- DBConnection.Username := UserName.Text;
36- DBConnection.Password := Password.Text;
37- // Now we've set up our connection, visually show that
38- // changes are not possibly any more
39- ServerName.ReadOnly:=true;
40- DatabaseName.ReadOnly:=true;
41- UserName.ReadOnly:=true;
42- Password.ReadOnly:=true;
43- end;
44- SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
45- DBConnection.Connected:= True;
46- SQLTransaction1.Active:= True;
47- SQLQuery1.Open;
48-end;
31+ begin
32+ SQLQuery1.Close;
33+ //Connection settings for Firebird/Interbase database
34+ //only needed when we have not yet connected:
35+ if not DBConnection.Connected then
36+ begin
37+ DBConnection.HostName := ServerName.Text;
38+ DBConnection.DatabaseName := DatabaseName.Text;
39+ DBConnection.Username := UserName.Text;
40+ DBConnection.Password := Password.Text;
41+ // Now we've set up our connection, visually show that
42+ // changes are not possibly any more
43+ ServerName.ReadOnly:=true;
44+ DatabaseName.ReadOnly:=true;
45+ UserName.ReadOnly:=true;
46+ Password.ReadOnly:=true;
47+ end;
48+ SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
49+ DBConnection.Connected:= True;
50+ SQLTransaction1.Active:= True;
51+ SQLQuery1.Open;
52+ end;
4953```
5054
51-Maintenant exécutez et testez si vous êtes connectés.
55+Maintenant exécutez et testez si vous êtes connectés.
5256
5357#### SQLite, autres bases de données
5458
55-Adaptez la propriété Text dans le TEdit comme demandé ; p.ex. `employee.sqlite` pour SQLite.
56-
57-For SQLite, la spécification des HostName, Username et password n'a pas de sens, donc vous pouvez omettre ces TEddits, commentez l'affectation des valeurs correspondantes dans DBConnection dans le code du dessus. Pour FireBird incorporé, forcez en dur le UserName à SYSDBA ; cela ne fera aucun mal si SQLite est utilisé.
59+Adaptez la propriété Text dans le TEdit comme demandé ; p.ex. `employee.sqlite` pour SQLite.
5860
59-Le code ressemblera à quelque chose comme cela :
61+For SQLite, la spécification des HostName, Username et password n'a pas de sens, donc vous pouvez omettre ces TEddits, commentez l'affectation des valeurs correspondantes dans DBConnection dans le code du dessus. Pour FireBird incorporé, forcez en dur le UserName à SYSDBA ; cela ne fera aucun mal si SQLite est utilisé.
6062
61-``` pascal
63+Le code ressemblera à quelque chose comme cela :
64+```
6265procedure TForm1.Button1Click(Sender: TObject);
63-begin
64- SQLQuery1.Close;
65- //Connection settings for embedded databases
66- //only needed when we have not yet connected:
67- if not DBConnection.Connected then
68- begin
69- DBConnection.DatabaseName := DatabaseName.Text;
70- DBConnection.UserName := 'SYSDBA'; //Firebird embedded needs this; doesn't harm if using SQLite
71- // Now we've set up our connection, visually show that
72- // changes are not possibly any more
73- DatabaseName.ReadOnly:=true;
74- end;
75- SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
76- DBConnection.Connected:= True;
77- SQLTransaction1.Active:= True;
78- SQLQuery1.Open;
79-end;
66+ begin
67+ SQLQuery1.Close;
68+ //Connection settings for embedded databases
69+ //only needed when we have not yet connected:
70+ if not DBConnection.Connected then
71+ begin
72+ DBConnection.DatabaseName := DatabaseName.Text;
73+ DBConnection.UserName := 'SYSDBA'; //Firebird embedded needs this; doesn't harm if using SQLite
74+ // Now we've set up our connection, visually show that
75+ // changes are not possibly any more
76+ DatabaseName.ReadOnly:=true;
77+ end;
78+ SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
79+ DBConnection.Connected:= True;
80+ SQLTransaction1.Active:= True;
81+ SQLQuery1.Open;
82+ end;
8083```
8184
8285### Filtrage de données
8386
84-Souvent, une table contient une énorme quantité de données que l'utilisateur ne veut(ou ne doit) pas voir (et cela prend beaucoup de temps à requêter et voyage à travers le réseau). Supposons que seuls les clients des USA devraient être affichés. En conséquence, l'ordre SQL dans 'SQLQuery1' ressemblera à quelque chose comme ceci :
85-
86-``` SQL
87+Souvent, une table contient une énorme quantité de données que l'utilisateur ne veut(ou ne doit) pas voir (et cela prend beaucoup de temps à requêter et voyage à travers le réseau). Supposons que seuls les clients des USA devraient être affichés. En conséquence, l'ordre SQL dans 'SQLQuery1' ressemblera à quelque chose comme ceci :
88+```
8789select * from CUSTOMER where COUNTRY = 'USA'
8890```
8991
90-... qui devrait être transformé en quelque chose comme cela dans notre code :
91-
92-``` pascal
92+... qui devrait être transformé en quelque chose comme cela dans notre code :
93+```
9394SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = 'USA'';
9495```
9596
96-Il y a deux raisons pour lesquelles nous n'utilisaeraon pas cette ordre dans notre exemple d'application :
97-
98-D'abord il y a un problème avec l'emploi des aapostrophes. Le compilateur interprétera cela l'apostrophe avant USA comme une apostrophe de fermeture (la première apostrophe est devant le SELECT * FROM...), ainsi l'ordre SQL va devenir invalide. Solution : il faut doubler les apostrophes intérieures :
97+Il y a deux raisons pour lesquelles nous n'utilisaeraon pas cette ordre dans notre exemple d'application :
9998
100-``` pascal
99+D'abord il y a un problème avec l'emploi des aapostrophes. Le compilateur interprétera cela l'apostrophe avant USA comme une apostrophe de fermeture (la première apostrophe est devant le SELECT * FROM...), ainsi l'ordre SQL va devenir invalide. Solution : il faut doubler les apostrophes intérieures :
100+```
101101SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = ''USA''';
102102```
103103
104-Ensuite, raison plus importante dans les faits, nous ignorons probablement ce quelles contraintes l'utilisateur voudra filtrer. Nous ns voulons pas limiter la flexibilité de l'utilisateur.
105-
106-Pour obtenir cette flexibilité, nous changeons en premier notre ordre SQL et remplaçons 'USA' par une marque substitutive (*placeholder*, un paramètre pour parler SQL) : changez la procédure Button1click et remplacez :
104+Ensuite, raison plus importante dans les faits, nous ignorons probablement ce quelles contraintes l'utilisateur voudra filtrer. Nous ns voulons pas limiter la flexibilité de l'utilisateur.
107105
108-``` pascal
106+Pour obtenir cette flexibilité, nous changeons en premier notre ordre SQL et remplaçons 'USA' par une marque substitutive (_placeholder_ , un paramètre pour parler SQL) : changez la procédure Button1click et remplacez :
107+```
109108SQLQuery1.SQL.Text := 'select * from CUSTOMER';
110109```
111110
112-par :
113-
114-``` pascal
111+par :
112+```
115113SQLQuery1.SQL.Text:= 'select * from CUSTOMER where COUNTRY = :COUNTRY';
116114```
117115
118-Dasn SQLDB de FPC, le paramètre SQL est marqué par un caractère deux-points (d'autres langages/environnements utilisent une autre convention comme ?). Pour permettre à l'utilisateur d'entrer une valeur pour le filtre, nous plaçons un composant *TEdit* sur notre fiche. Supprimez a valeur dans la propriété 'Text'. Nous pouvons maintenant prendre le texte entré dans le TEdit et remplir le paramètre SQL COUNTRY en utilisant la propriété 'Params' du TSQLQuery. Ajoutez ce qui suit dans l'instruction précédente :
119-
120-``` pascal
116+Dasn SQLDB de FPC, le paramètre SQL est marqué par un caractère deux-points (d'autres langages/environnements utilisent une autre convention comme ?). Pour permettre à l'utilisateur d'entrer une valeur pour le filtre, nous plaçons un composant _TEdit_ sur notre fiche. Supprimez a valeur dans la propriété 'Text'. Nous pouvons maintenant prendre le texte entré dans le TEdit et remplir le paramètre SQL COUNTRY en utilisant la propriété 'Params' du TSQLQuery. Ajoutez ce qui suit dans l'instruction précédente :
117+```
121118SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
122119```
123120
124-Le paramètre peut être spécifié par sa position ou son nom. L'utilisation du nom améliorera la lisibilité du code source, et évidemment aide si vous insérez plus de paramètre au milieu des paramètres existants.
125-
126-Nous utilisons '.AsString' pour affecter une valeur chaîne au paramètre ; il y a des affectation de propriété équivalente pour les paramètres entiers, booléens etc.
121+Le paramètre peut être spécifié par sa position ou son nom. L'utilisation du nom améliorera la lisibilité du code source, et évidemment aide si vous insérez plus de paramètre au milieu des paramètres existants.
127122
128-Jusqu'à maintenant, le code nous forçe à utiliser un filtre. Si un utilisateur spécifie une valeur vide dans la zone de saisie, aucun enregistrement ne sera affiché. Ce n'est sans doute pas ce que nous voulons. Testons la valeur vide et construisons la requête en conséquence. Nous devrions nous retrouver avec une procédure comme celle-ci :
123+Nous utilisons '.AsString' pour affecter une valeur chaîne au paramètre ; il y a des affectation de propriété équivalente pour les paramètres entiers, booléens etc.
129124
130-``` pascal
125+Jusqu'à maintenant, le code nous forçe à utiliser un filtre. Si un utilisateur spécifie une valeur vide dans la zone de saisie, aucun enregistrement ne sera affiché. Ce n'est sans doute pas ce que nous voulons. Testons la valeur vide et construisons la requête en conséquence. Nous devrions nous retrouver avec une procédure comme celle-ci :
126+```
131127procedure TForm1.Button1Click(Sender: TObject);
132-begin
133- SQLQuery1.Close;
134- //Connection settings for Firebird/Interbase database
135- //only needed when we have not yet connected:
136- if not DBConnection.Connected then
137- begin
138- DBConnection.HostName := ServerName.Text;
139- DBConnection.DatabaseName := DatabaseName.Text;
140- DBConnection.Username := UserName.Text;
141- DBConnection.Password := Password.Text;
142- // Now we've set up our connection, visually show that
143- // changes are not possibly any more
144- ServerName.ReadOnly:=true;
145- DatabaseName.ReadOnly:=true;
146- UserName.ReadOnly:=true;
147- Password.ReadOnly:=true;
148- end;
149- // Show all records, or filter if user specified a filter criterium
150- if Edit1.Text='' then
151- SQLQuery1.SQL.Text := 'select * from CUSTOMER'
152- else
153- begin
154- SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
155- SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
156- end;
157- DBConnection.Connected:= True;
158- SQLTransaction1.Active:= True;
159- SQLQuery1.Open;
160-end;
128+ begin
129+ SQLQuery1.Close;
130+ //Connection settings for Firebird/Interbase database
131+ //only needed when we have not yet connected:
132+ if not DBConnection.Connected then
133+ begin
134+ DBConnection.HostName := ServerName.Text;
135+ DBConnection.DatabaseName := DatabaseName.Text;
136+ DBConnection.Username := UserName.Text;
137+ DBConnection.Password := Password.Text;
138+ // Now we've set up our connection, visually show that
139+ // changes are not possibly any more
140+ ServerName.ReadOnly:=true;
141+ DatabaseName.ReadOnly:=true;
142+ UserName.ReadOnly:=true;
143+ Password.ReadOnly:=true;
144+ end;
145+ // Show all records, or filter if user specified a filter criterium
146+ if Edit1.Text='' then
147+ SQLQuery1.SQL.Text := 'select * from CUSTOMER'
148+ else
149+ begin
150+ SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
151+ SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
152+ end;
153+ DBConnection.Connected:= True;
154+ SQLTransaction1.Active:= True;
155+ SQLQuery1.Open;
156+ end;
161157```
162158
163-Maintenant vous pouvez jouer un peu avec le filtrage en utilisant Edit1. Si vous entrez un pays qui n'est pas présent dans la base de données, une grille affichée est vide.
159+Maintenant vous pouvez jouer un peu avec le filtrage en utilisant Edit1. Si vous entrez un pays qui n'est pas présent dans la base de données, une grille affichée est vide.
164160
165161### Gestion des erreurs
166162
167-L'application devrait tourner mais parfois des problèmes arrivent. Les bases de données, même les bases incorporées, peuvent planter (i.e. quand le serveur de base de données plante, le disque est plein, ou juste provoqué par un bug), laissant l'application en suspens.
168-
169-L'accès à une base de données (tout processus externe, en vrai) devrait donc *toujours* être intégré dans une construction try ... except et/ou try ... finally. Cela garantit que les erreurs de bases de données sont traitées et que l'utilisateur n'est pas laissé à l'abandon. Une routine rudimentaire pour notre exemple peut ressembler à ceci :
163+L'application devrait tourner mais parfois des problèmes arrivent. Les bases de données, même les bases incorporées, peuvent planter (i.e. quand le serveur de base de données plante, le disque est plein, ou juste provoqué par un bug), laissant l'application en suspens.
170164
171-``` pascal
165+L'accès à une base de données (tout processus externe, en vrai) devrait donc _toujours_ être intégré dans une construction try ... except et/ou try ... finally. Cela garantit que les erreurs de bases de données sont traitées et que l'utilisateur n'est pas laissé à l'abandon. Une routine rudimentaire pour notre exemple peut ressembler à ceci :
166+```
172167begin
173- try
174- SQLQuery1.Close;
175- ...
176- SQLQuery1.Open;
177- except
178- //We could use EDatabaseError which is a general database error, but we're dealing with Firebird/Interbase, so:
179- on E: EDatabaseError do
180- begin
181- MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
182- Edit1.Text:='';
168+ try
169+ SQLQuery1.Close;
170+ ...
171+ SQLQuery1.Open;
172+ except
173+ //We could use EDatabaseError which is a general database error, but we're dealing with Firebird/Interbase, so:
174+ on E: EDatabaseError do
175+ begin
176+ MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
177+ Edit1.Text:='';
178+ end;
179+ end;
183180 end;
184- end;
185-end;
186181```
187182
188183#### SQLite, PostgreSQL, autres bases de données
189184
190-Vous pouvez soit utiliser la plus générique EDatabaseError, ou, si disponible, votre propre dérivé de EDatabaseError, si vous avez besoin de plus de détail. P.ex. SQLite et le pilote PostgreSQL dans FPC 2.6.1 et antérieur n'ont pas de E*DatabaseError spécialisé; vous devez utiliser EDatabaseError. PostgreSQL sur FPC du tronc (version de développement) a un dérivé EPQDatabaseError.
185+Vous pouvez soit utiliser la plus générique EDatabaseError, ou, si disponible, votre propre dérivé de EDatabaseError, si vous avez besoin de plus de détail. P.ex. SQLite et le pilote PostgreSQL dans FPC 2.6.1 et antérieur n'ont pas de E*DatabaseError spécialisé; vous devez utiliser EDatabaseError. PostgreSQL sur FPC du tronc (version de développement) a un dérivé EPQDatabaseError.
191186
192187## Edition des données utilisant la grille
193188
194189### Edition
195190
196-Jusqu'à maintenant, si vous essayiez d'éditer des données dans la grille, les modifications ne pourront pas être enregistrés. Ceci parce que le *SQLQuery1* n'est pas construit pour envoyer les changements vers la transaction de base de données au bon moment.
197-
198-Nous avons besion de corriger cela et donc de faire le commit de la base de données, ainsi tous les changements seront écrit. Pour ceci, vous devrez utiliser du code comme ceci :
191+Jusqu'à maintenant, si vous essayiez d'éditer des données dans la grille, les modifications ne pourront pas être enregistrés. Ceci parce que le _SQLQuery1_ n'est pas construit pour envoyer les changements vers la transaction de base de données au bon moment.
199192
200-``` pascal
193+Nous avons besion de corriger cela et donc de faire le commit de la base de données, ainsi tous les changements seront écrit. Pour ceci, vous devrez utiliser du code comme ceci :
194+```
201195SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
202-SQLTransaction1.Commit; //... and commit them using the transaction.
203-//SQLTransaction1.Active now is false
196+ SQLTransaction1.Commit; //... and commit them using the transaction.
197+ //SQLTransaction1.Active now is false
204198```
205199
206-Nous voulons garantir que toutes les éditions (insertions, mises à jour, suppressions) sont écrites dans la base de données :
207-
208-- quand l'utilisateur change le critère de filtrage et presse le bouton poutr interroger la base de données.
209-- quand la fiche est fermée.
200+Nous voulons garantir que toutes les éditions (insertions, mises à jour, suppressions) sont écrites dans la base de données :
210201
211-Il est pertinent de faire une procédure séparée pour ceci qui est appelée pour ces deux instances. Allez au code et ajoutez une ligne vide ici :
202+ * quand l'utilisateur change le critère de filtrage et presse le bouton poutr interroger la base de données.
203+ * quand la fiche est fermée.
212204
213-``` pascal
214- TForm1 = class(TForm)
215- Button1: TButton;
216- Datasource1: TDatasource;
217- DBGrid1: TDBGrid;
218- Edit1: TEdit;
219- DBConnection: TIBConnection;
220- SQLQuery1: TSQLQuery;
221- SQLTransaction1: TSQLTransaction;
222-*****insert the empty line here****
223- procedure Button1click(Sender: TObject);
224- procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
225- private
205+Il est pertinent de faire une procédure séparée pour ceci qui est appelée pour ces deux instances. Allez au code et ajoutez une ligne vide ici :
226206```
227-
228-puis tapez :
229-
230-``` pascal
231- procedure SaveChanges;
207+TForm1 = class(TForm)
208+ Button1: TButton;
209+ Datasource1: TDatasource;
210+ DBGrid1: TDBGrid;
211+ Edit1: TEdit;
212+ DBConnection: TIBConnection;
213+ SQLQuery1: TSQLQuery;
214+ SQLTransaction1: TSQLTransaction;
215+ *****insert the empty line here****
216+ procedure Button1click(Sender: TObject);
217+ procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
218+ private
232219```
233220
234-pressez shift-ctrl-c (combinaison par défaut) pour laisser la complétion de code créer le corps de la procédure correspondante.
221+puis tapez :
222+```
223+procedure SaveChanges;
224+```
235225
236-Nous avons besoin d'ajouter la gestion d'erreur et contrôler que la transaction est active - souvenez-vous, ce code est aussi appelé quand le bouton est actionné la première fois, quand la transaction n'est pas encore active. Nous obtenons :
226+pressez shift-ctrl-c (combinaison par défaut) pour laisser la complétion de code créer le corps de la procédure correspondante.
237227
238-``` pascal
228+Nous avons besoin d'ajouter la gestion d'erreur et contrôler que la transaction est active - souvenez-vous, ce code est aussi appelé quand le bouton est actionné la première fois, quand la transaction n'est pas encore active. Nous obtenons :
229+```
239230procedure Tform1.SaveChanges;
240-// Saves edits done by user, if any.
241-begin
242- try
243- if SQLTransaction1.Active then
244- // Only if we are within a started transaction;
245- // otherwise you get "Operation cannot be performed on an inactive dataset"
246- begin
247- SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
248- SQLTransaction1.Commit; //... and commit them using the transaction.
249- //SQLTransaction1.Active now is false
250- end;
251- except
252- on E: EDatabaseError do
231+ // Saves edits done by user, if any.
253232 begin
254- MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
255- E.Message, mtError, [mbOK], 0);
256- Edit1.Text := '';
233+ try
234+ if SQLTransaction1.Active then
235+ // Only if we are within a started transaction;
236+ // otherwise you get "Operation cannot be performed on an inactive dataset"
237+ begin
238+ SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
239+ SQLTransaction1.Commit; //... and commit them using the transaction.
240+ //SQLTransaction1.Active now is false
241+ end;
242+ except
243+ on E: EDatabaseError do
244+ begin
245+ MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
246+ E.Message, mtError, [mbOK], 0);
247+ Edit1.Text := '';
248+ end;
249+ end;
257250 end;
258- end;
259-end;
260251```
261252
262-Maintenant nous avons besoin d'appeler cette procédure aux moments appropriés :
263-
264-``` pascal
253+Maintenant nous avons besoin d'appeler cette procédure aux moments appropriés :
254+```
265255procedure Tform1.Button1click(Sender: TObject);
266-begin
267- SaveChanges; //Saves changes and commits transaction
268- try
269- SQLQuery1.Close;
270-....
256+ begin
257+ SaveChanges; //Saves changes and commits transaction
258+ try
259+ SQLQuery1.Close;
260+ ....
271261```
272262
273-et
274-
275-``` pascal
263+et
264+```
276265procedure Tform1.Formclose(Sender: TObject; var Closeaction: Tcloseaction);
277-begin
278- SaveChanges; //Saves changes and commits transaction
279- SQLQuery1.Close;
280-....
266+ begin
267+ SaveChanges; //Saves changes and commits transaction
268+ SQLQuery1.Close;
269+ ....
281270```
282271
283-Maintenant testez et voyez si les modifications réalisées dans la grille sont enregistrées dans la base de données.
272+Maintenant testez et voyez si les modifications réalisées dans la grille sont enregistrées dans la base de données.
284273
285274### Masquage de la colonne de clé primaire
286275
287-Souvent, vous ne voulez pas que vos utilisateurs voient les clés primaires auto-incrémentées car elles ne servent qu'à maintenir l'intégrité référentielle. Si les utilisateurs les voient, ils voudront peut-être essayer de modifier les numéros, se fâcher lorsque les chiffres changent, qu'il y ait des lacunes dans les chiffres, etc.
288-
289-Dans notre exemple, CUST_NO est la clé primaire, avec du contenu auto-généré par Firebird en utilisant des triggers et un générateur (séquence). ,Ceci veut dire que vous pouvez insérer un nouvel enregistrement sans spécifier le champ CUST_NO ; Firebird créera la valeur du champ automatiquement.
276+Souvent, vous ne voulez pas que vos utilisateurs voient les clés primaires auto-incrémentées car elles ne servent qu'à maintenir l'intégrité référentielle. Si les utilisateurs les voient, ils voudront peut-être essayer de modifier les numéros, se fâcher lorsque les chiffres changent, qu'il y ait des lacunes dans les chiffres, etc.
290277
291-Nous pouvons changer simplement notre propriété SQLQuery1.SQL.Text pour ne pas inclure CUST_NO, mais cela amènera à des problèmes lors de l'édition des données - la clé primaire est demandée pour identifier l'enregistement/ ligne en question.
278+Dans notre exemple, CUST_NO est la clé primaire, avec du contenu auto-généré par Firebird en utilisant des triggers et un générateur (séquence). ,Ceci veut dire que vous pouvez insérer un nouvel enregistrement sans spécifier le champ CUST_NO ; Firebird créera la valeur du champ automatiquement.
292279
293-Donc utilisons une astuce pour récupérer toutes les colonnes/champs mais empêcher la grille d'afficher le premier champ, CUST_NO : dans la procédure Button1Click, ajoutez le code comme cela :
280+Nous pouvons changer simplement notre propriété SQLQuery1.SQL.Text pour ne pas inclure CUST_NO, mais cela amènera à des problèmes lors de l'édition des données - la clé primaire est demandée pour identifier l'enregistement/ ligne en question.
294281
295-``` pascal
282+Donc utilisons une astuce pour récupérer toutes les colonnes/champs mais empêcher la grille d'afficher le premier champ, CUST_NO : dans la procédure Button1Click, ajoutez le code comme cela :
283+```
296284procedure Tform1.Button1click(Sender: TObject);
297-begin
298-...
299- SQLQuery1.Open;
300- // Hide the primary key column which is the first column in our queries.
301- // We can only do this once the DBGrid has created the columns
302- DBGrid1.Columns[0].Visible:=false;
285+ begin
286+ ...
287+ SQLQuery1.Open;
288+ // Hide the primary key column which is the first column in our queries.
289+ // We can only do this once the DBGrid has created the columns
290+ DBGrid1.Columns[0].Visible:=false;
303291```
304292
305-Recompilez et contrôlez pour voir si la colonne de clé primaire est effectivement cachée.
293+Recompilez et contrôlez pour voir si la colonne de clé primaire est effectivement cachée.
306294
307295#### SQLite, autres bases de données
308296
309-- Autres base de données : de nombreuses autres bases de données utilisent un type de champ 'autonumber' ou 'autoinc' pour fournir du contenu de champ auto-généré. Essayez de changer votre définition de table pour voir si cela fonctionne.
310-- Sqlite : l'exmple du dessus fonctionne pour SQLite car nous utilisons une clé primaire entière. Voir la the [documentation](http://www.sqlite.org/autoinc.html) pour des détails.
297+ * Autres base de données : de nombreuses autres bases de données utilisent un type de champ 'autonumber' ou 'autoinc' pour fournir du contenu de champ auto-généré. Essayez de changer votre définition de table pour voir si cela fonctionne.
298+ * Sqlite : l'exmple du dessus fonctionne pour SQLite car nous utilisons une clé primaire entière. Voir la the [documentation](<http://www.sqlite.org/autoinc.html>) pour des détails.
311299
312300### Insertion de nouvelles données
313301
314-Si vous insérez de nouveaux enregistements/lignes sans aucune information CUST_NO, vous pouvez avoir remarqué que vous obtenez le message d'erreur : `Field CUST_NO is required, but not supplied`. Ceci survient aussi si vous cachez la colonne CUST_NO comme dans la section précédente.
315-
316-La raison : Lazarus pense que CUST_NO est requis. Cela n'est pas étrange, car c'est une clé primaire et la définition de table sous-jacente dans la base de données dit qu'il est requis.
302+Si vous insérez de nouveaux enregistements/lignes sans aucune information CUST_NO, vous pouvez avoir remarqué que vous obtenez le message d'erreur : `Field CUST_NO is required, but not supplied`. Ceci survient aussi si vous cachez la colonne CUST_NO comme dans la section précédente.
317303
318-Si nous pouvons intimer à Lazarus que ce champ n'est pas actuellement requis, nous pouvons passer des valeurs vides (=valeurs à NULL) à la base de données. Heureusement, un objet champ de requête a une propriété *Required* qui sert exactement à cela.
304+La raison : Lazarus pense que CUST_NO est requis. Cela n'est pas étrange, car c'est une clé primaire et la définition de table sous-jacente dans la base de données dit qu'il est requis.
319305
320-Modifiez le code en quelque chose comme :
306+Si nous pouvons intimer à Lazarus que ce champ n'est pas actuellement requis, nous pouvons passer des valeurs vides (=valeurs à NULL) à la base de données. Heureusement, un objet champ de requête a une propriété _Required_ qui sert exactement à cela.
321307
322-``` pascal
323- SQLQuery1.Open;
324- {
325- Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, e.g.:
326- Field CUST_NO is required, but not supplied
327- We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
328- when inserting new records.
329- }
330- SQLQuery1.FieldByName('CUST_NO').Required:=false;
331- // Hide the primary key column which is the first column in our queries.
332- // We can only do this once the DBGrid has created the columns
333- DBGrid1.Columns[0].Visible:=false;
308+Modifiez le code en quelque chose comme :
334309```
310+SQLQuery1.Open;
311+ {
312+ Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, e.g.:
313+ Field CUST_NO is required, but not supplied
314+ We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
315+ when inserting new records.
316+ }
317+ SQLQuery1.FieldByName('CUST_NO').Required:=false;
318+ // Hide the primary key column which is the first column in our queries.
319+ // We can only do this once the DBGrid has created the columns
320+ DBGrid1.Columns[0].Visible:=false;
321+```
335322
336323### Suppression de données
337324
338-Vous pouvez laisser les utilisateurs employer la souris pour cela. Vous n'avez même pas besoin de code une seule ligne pour cette fonctionnalité.
339-
340-Sur l'onglet 'Data controls', sélectionner le composant *TDBNavigator* et posez-le sur la fiche, au dessus de la grille.
325+Vous pouvez laisser les utilisateurs employer la souris pour cela. Vous n'avez même pas besoin de code une seule ligne pour cette fonctionnalité.
341326
342-Pour indiquer à quoi est relié le navigateur, mettez votre composant DataSource (DataSource1) dans sa propriété DataSource en utilisant l'inspecteur d'objet.
327+Sur l'onglet 'Data controls', sélectionner le composant _TDBNavigator_ et posez-le sur la fiche, au dessus de la grille.
343328
344-Maintenant vous pouvez utiliser le bouton sur le *DBNavigator* pour supprimer des enregistrements, mais aussi pour en insérer et vous déplacer parmi les enregistrements. Aussi, en éditant les cellules/champs, vous pouvez utiliser le bouton *Cancel* pour annuler vos éditions.
329+Pour indiquer à quoi est relié le navigateur, mettez votre composant DataSource (DataSource1) dans sa propriété DataSource en utilisant l'inspecteur d'objet.
345330
346-Pour permettre à l'utilisateur de supprimer la ligne sur laquelle ils sont dans la grille en utilisant la touche `Delete`, ajoutez l'unité *LCLType* (elle contient les définitions des codes de touche) à votre clause uses :
331+Maintenant vous pouvez utiliser le bouton sur le _DBNavigator_ pour supprimer des enregistrements, mais aussi pour en insérer et vous déplacer parmi les enregistrements. Aussi, en éditant les cellules/champs, vous pouvez utiliser le bouton _Cancel_ pour annuler vos éditions.
347332
348-``` pascal
333+Pour permettre à l'utilisateur de supprimer la ligne sur laquelle ils sont dans la grille en utilisant la touche `Delete`, ajoutez l'unité _LCLType_ (elle contient les définitions des codes de touche) à votre clause uses :
334+```
349335uses
350- Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
351- Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;
336+ Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
337+ Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;
352338```
353339
354-... il faut coder l'événement KeyUppour la grille, qui survient quand une touche est relâchée dans la grille. Toutefois; nous avons besoin de contrôler que l'utilisateur n'est pas en train de modifier un champ - comme il peut utiliser la touche `Delete` pour supprimer des lettres plutôt que l'enregistrement sur lequel il travaille.
355-
356-Sélectionnez la grille et allez sur les événements pour créer l'événement OnKeyUp comme ceci :
340+... il faut coder l'événement KeyUppour la grille, qui survient quand une touche est relâchée dans la grille. Toutefois; nous avons besoin de contrôler que l'utilisateur n'est pas en train de modifier un champ - comme il peut utiliser la touche `Delete` pour supprimer des lettres plutôt que l'enregistrement sur lequel il travaille.
357341
358-``` pascal
342+Sélectionnez la grille et allez sur les événements pour créer l'événement OnKeyUp comme ceci :
343+```
359344procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
360- );
361-begin
362- // Check for del key being hit and delete the current record in response
363- // as long as we're not editing data
364- if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
365- begin
366- //... delete current record and apply updates to db:
367- SQLQuery1.Delete;
368- SQLQuery1.ApplyUpdates;
369- end;
370-end;
345+ );
346+ begin
347+ // Check for del key being hit and delete the current record in response
348+ // as long as we're not editing data
349+ if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
350+ begin
351+ //... delete current record and apply updates to db:
352+ SQLQuery1.Delete;
353+ SQLQuery1.ApplyUpdates;
354+ end;
355+ end;
371356```
372357
373-> **Note:** Par défaut, dans la propriété Options du TDBGrid, dgDisableDelete est mise à False, ce qui veut dire que l'utilisateur peut supprimer un enregistrement avec la combinaison `ctrl`+`delete`. Vous pouvez ne pas désirer ce comportement.
358+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Remarque:** Par défaut, dans la propriété Options du TDBGrid, dgDisableDelete est mise à False, ce qui veut dire que l'utilisateur peut supprimer un enregistrement avec la combinaison `ctrl`+`delete`. Vous pouvez ne pas désirer ce comportement.
374359
375360## Résumé
376361
377-Si vous avez tout suivi jusqu'à maintenant, vous pouvez récupérer des données de la base, les filtrer, les modifier, les supprimer dans la grille. Votre code ressemble à quelque chose comme cela.
378-
379-``` pascal
362+Si vous avez tout suivi jusqu'à maintenant, vous pouvez récupérer des données de la base, les filtrer, les modifier, les supprimer dans la grille. Votre code ressemble à quelque chose comme cela.
363+```
380364unit sqldbtutorial1unit;
381-
382-{$mode objfpc}{$H+}
383-
384-interface
385-
386-uses
387- Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
388- Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;
389-type
390-
391- { TForm1 }
392-
393- TForm1 = class(TForm)
394- Button1: TButton;
395- DatabaseName: TEdit;
396- Datasource1: TDatasource;
397- DBGrid1: TDBGrid;
398- Dbnavigator1: Tdbnavigator;
399- Edit1: TEdit;
400- Label2: Tlabel;
401- Label3: Tlabel;
402- Label4: Tlabel;
403- Label5: Tlabel;
404- Password: TEdit;
405- UserName: TEdit;
406- ServerName: TEdit;
407- DBConnection: TIBConnection;
408- Label1: TLabel;
409- SQLQuery1: TSQLQuery;
410- SQLTransaction1: TSQLTransaction;
411- procedure SaveChanges;
412- procedure Button1click(Sender: TObject);
413- procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
414- private
415- { private declarations }
416- public
417- { public declarations }
418- end;
419-
420-var
421- Form1: TForm1;
422-
423-implementation
424-
425-{$R *.lfm}
426-
427-{ TForm1 }
428-
429-procedure Tform1.Savechanges;
430-// Saves edits done by user, if any.
431-begin
432- try
433- if SQLTransaction1.Active then
434- // Only if we are within a started transaction
435- // otherwise you get "Operation cannot be performed on an inactive dataset"
436- begin
437- SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
438- SQLTransaction1.Commit; //... and commit them using the transaction.
439- //SQLTransaction1.Active now is false
440- end;
441- except
442- on E: EDatabaseError do
365+
366+ {$mode objfpc}{$H+}
367+
368+ interface
369+
370+ uses
371+ Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
372+ Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;
373+ type
374+
375+ { TForm1 }
376+
377+ TForm1 = class(TForm)
378+ Button1: TButton;
379+ DatabaseName: TEdit;
380+ Datasource1: TDatasource;
381+ DBGrid1: TDBGrid;
382+ Dbnavigator1: Tdbnavigator;
383+ Edit1: TEdit;
384+ Label2: Tlabel;
385+ Label3: Tlabel;
386+ Label4: Tlabel;
387+ Label5: Tlabel;
388+ Password: TEdit;
389+ UserName: TEdit;
390+ ServerName: TEdit;
391+ DBConnection: TIBConnection;
392+ Label1: TLabel;
393+ SQLQuery1: TSQLQuery;
394+ SQLTransaction1: TSQLTransaction;
395+ procedure SaveChanges;
396+ procedure Button1click(Sender: TObject);
397+ procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
398+ private
399+ { private declarations }
400+ public
401+ { public declarations }
402+ end;
403+
404+ var
405+ Form1: TForm1;
406+
407+ implementation
408+
409+ {$R *.lfm}
410+
411+ { TForm1 }
412+
413+ procedure Tform1.Savechanges;
414+ // Saves edits done by user, if any.
443415 begin
444- MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
445- E.Message, mtError, [mbOK], 0);
446- Edit1.Text := '';
416+ try
417+ if SQLTransaction1.Active then
418+ // Only if we are within a started transaction
419+ // otherwise you get "Operation cannot be performed on an inactive dataset"
420+ begin
421+ SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
422+ SQLTransaction1.Commit; //... and commit them using the transaction.
423+ //SQLTransaction1.Active now is false
424+ end;
425+ except
426+ on E: EDatabaseError do
427+ begin
428+ MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
429+ E.Message, mtError, [mbOK], 0);
430+ Edit1.Text := '';
431+ end;
432+ end;
447433 end;
448- end;
449-end;
450-
451-procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
452- );
453-begin
454- // Check for del key being hit and delete the current record in response
455- // as long as we're not editing data
456- if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
457- begin
458- //... delete current record and apply updates to db:
459- SQLQuery1.Delete;
460- SQLQuery1.ApplyUpdates;
461- end;
462-end;
463-
464-procedure Tform1.Button1click(Sender: TObject);
465-begin
466- SaveChanges; //Saves changes and commits transaction
467- try
468- SQLQuery1.Close;
469- //Connection settings for Firebird/Interbase database
470- //only needed when we have not yet connected:
471- if not DBConnection.Connected then
434+
435+ procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
436+ );
472437 begin
473- DBConnection.HostName := ServerName.Text;
474- DBConnection.DatabaseName := DatabaseName.Text;
475- DBConnection.Username := UserName.Text;
476- DBConnection.Password := Password.Text;
477- // Now we've set up our connection, visually show that
478- // changes are not possibly any more
479- ServerName.ReadOnly:=true;
480- DatabaseName.ReadOnly:=true;
481- UserName.ReadOnly:=true;
482- Password.ReadOnly:=true;
483- end;
484- // Show all records, or filter if user specified a filter criterium
485- if Edit1.Text='' then
486- SQLQuery1.SQL.Text := 'select * from CUSTOMER'
487- else
438+ // Check for del key being hit and delete the current record in response
439+ // as long as we're not editing data
440+ if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
441+ begin
442+ //... delete current record and apply updates to db:
443+ SQLQuery1.Delete;
444+ SQLQuery1.ApplyUpdates;
445+ end;
446+ end;
447+
448+ procedure Tform1.Button1click(Sender: TObject);
488449 begin
489- SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
490- SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
450+ SaveChanges; //Saves changes and commits transaction
451+ try
452+ SQLQuery1.Close;
453+ //Connection settings for Firebird/Interbase database
454+ //only needed when we have not yet connected:
455+ if not DBConnection.Connected then
456+ begin
457+ DBConnection.HostName := ServerName.Text;
458+ DBConnection.DatabaseName := DatabaseName.Text;
459+ DBConnection.Username := UserName.Text;
460+ DBConnection.Password := Password.Text;
461+ // Now we've set up our connection, visually show that
462+ // changes are not possibly any more
463+ ServerName.ReadOnly:=true;
464+ DatabaseName.ReadOnly:=true;
465+ UserName.ReadOnly:=true;
466+ Password.ReadOnly:=true;
467+ end;
468+ // Show all records, or filter if user specified a filter criterium
469+ if Edit1.Text='' then
470+ SQLQuery1.SQL.Text := 'select * from CUSTOMER'
471+ else
472+ begin
473+ SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
474+ SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
475+ end;
476+ DBConnection.Connected := True;
477+ SQLTransaction1.Active := True; //Starts a new transaction
478+ SQLQuery1.Open;
479+ {
480+ Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, i.e. error message:
481+ "Field CUST_NO is required, but not supplied"
482+ We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
483+ when inserting new records.
484+ }
485+ SQLQuery1.FieldByName('CUST_NO').Required:=false;
486+ {
487+ Hide the primary key column which is the first column in our queries.
488+ We can only do this once the DBGrid has created the columns
489+ }
490+ DBGrid1.Columns[0].Visible:=false;
491+ except
492+ // EDatabaseError is a general error;
493+ // you could also use one for your specific db, e.g.
494+ // use EIBDatabaseError for Firebird/Interbase
495+ on E: EDatabaseError do
496+ begin
497+ MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
498+ E.Message, mtError, [mbOK], 0);
499+ Edit1.Text := '';
500+ end;
501+ end;
491502 end;
492- DBConnection.Connected := True;
493- SQLTransaction1.Active := True; //Starts a new transaction
494- SQLQuery1.Open;
495- {
496- Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, i.e. error message:
497- "Field CUST_NO is required, but not supplied"
498- We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
499- when inserting new records.
500- }
501- SQLQuery1.FieldByName('CUST_NO').Required:=false;
502- {
503- Hide the primary key column which is the first column in our queries.
504- We can only do this once the DBGrid has created the columns
505- }
506- DBGrid1.Columns[0].Visible:=false;
507- except
508- // EDatabaseError is a general error;
509- // you could also use one for your specific db, e.g.
510- // use EIBDatabaseError for Firebird/Interbase
511- on E: EDatabaseError do
503+
504+ procedure Tform1.Formclose(Sender: TObject; var Closeaction: Tcloseaction);
512505 begin
513- MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
514- E.Message, mtError, [mbOK], 0);
515- Edit1.Text := '';
506+ SaveChanges; //Saves changes and commits transaction
507+ SQLQuery1.Close;
508+ SQLTransaction1.Active := False;
509+ DBConnection.Connected := False;
516510 end;
517- end;
518-end;
519-
520-procedure Tform1.Formclose(Sender: TObject; var Closeaction: Tcloseaction);
521-begin
522- SaveChanges; //Saves changes and commits transaction
523- SQLQuery1.Close;
524- SQLTransaction1.Active := False;
525- DBConnection.Connected := False;
526-end;
527-
528-end.
511+
512+ end.
529513```
530514
531515## Base de données incorporée sans modification de code
532516
533517### Firebird sur Windows
534518
535-Un bonus pour les utilisateurs de Firebird sur Windows ; si vous avez suivi ce tutoriel (même si vous n'avez fait que l'exemple de base), vous avez renommé la bibliothèque incorporée de Firebird `fbembed.dll` en `fbclient.dll`. avec ceci, Lazarus se connectera aux serveurs Firebird normaux (sur une machine distante ou sur votre machine locale). Toutefois, vous pouvez aussi copier la base de données `employee.fdb` dans votre dossier d'application, exécuter l'application, effacer le TEdit *Server name* et utiliser Firebird incorporé pour vous connecter directement au fichier de la base de données, sans configuration de serveur.
519+Un bonus pour les utilisateurs de Firebird sur Windows ; si vous avez suivi ce tutoriel (même si vous n'avez fait que l'exemple de base), vous avez renommé la bibliothèque incorporée de Firebird `fbembed.dll` en `fbclient.dll`. avec ceci, Lazarus se connectera aux serveurs Firebird normaux (sur une machine distante ou sur votre machine locale). Toutefois, vous pouvez aussi copier la base de données `employee.fdb` dans votre dossier d'application, exécuter l'application, effacer le TEdit _Server name_ et utiliser Firebird incorporé pour vous connecter directement au fichier de la base de données, sans configuration de serveur.
536520
537-Ceci est génial si vous souhaitez déployer des applications de base de données vers les utilisateurs finaux, mais ne souhaitez pas avoir du mal à installer des serveurs (vérifier si un serveur est déjà installé, s'il s'agit de la bonne version, faire en sorte que les utilisateurs vérifient les pare-feu, etc.).
521+Ceci est génial si vous souhaitez déployer des applications de base de données vers les utilisateurs finaux, mais ne souhaitez pas avoir du mal à installer des serveurs (vérifier si un serveur est déjà installé, s'il s'agit de la bonne version, faire en sorte que les utilisateurs vérifient les pare-feu, etc.).
538522
539-Voir [[Firebird embedded/fr|Firebird incorporé]] pour plus de détails.
523+Voir [[Firebird embedded/fr|Firebird incorporé]] pour plus de détails.
540524
541-Note (non vérifiée) : Depuis 2011, FPC tente de charger d'abord `fbembed.dll`, donc vous n'avez pas besoin de renommer `fbclient.dll` pour que cela fonctionne.
525+Note (non vérifiée) : Depuis 2011, FPC tente de charger d'abord `fbembed.dll`, donc vous n'avez pas besoin de renommer `fbclient.dll` pour que cela fonctionne.
542526
543527### Firebird sur Linux/OSX/Unix
544528
545-Il doit y avoir un moyen pour que cela fonctionne sur Linux / OSX. Voir [[Firebird/fr|Firebird]] pour les conseils et les liens. Les mises à jour du wiki sont les bienvenues.
529+Il doit y avoir un moyen pour que cela fonctionne sur Linux / OSX. Voir [[Firebird/fr|Firebird]] pour les conseils et les liens. Les mises à jour du wiki sont les bienvenues.
546530
547531### SQLite
548532
549-Certes, SQLite offre une fonctionnalité incorporée mais d'un autre côté, il ne permet pas de configuration client/serveur. En suivant le tutoriel du haut, vous pouvez voir cela qu'en basculant les bases de données (p.ex. SQLite et Firebird) ne fait pas tant de travail que cela.
533+Certes, SQLite offre une fonctionnalité incorporée mais d'un autre côté, il ne permet pas de configuration client/serveur. En suivant le tutoriel du haut, vous pouvez voir cela qu'en basculant les bases de données (p.ex. SQLite et Firebird) ne fait pas tant de travail que cela.
550534
551535### Autres bases de données
552536
553-Votre base de données peut offrir des fonctionnalités similaires. Des mises à jour de ce Wiki pour d'autres SGBD sont les bienvenues.
537+Votre base de données peut offrir des fonctionnalités similaires. Des mises à jour de ce Wiki pour d'autres SGBD sont les bienvenues.
554538
555539## Voir aussi
556540
557-- [[SQLdb Tutorial0/fr|SQLdb Tutorial0]] : Instructions pour configurer les tables et les données d'exemple pour la série de tutoriels.
558-- [[SQLdb Tutorial1/fr|SQLdb Tutorial1]] : 1re partie de la série de tutoriels sur les bases de données, montrant comment configurer une grille pour afficher les données.
559-- [[SQLdb Tutorial2/fr|SQLdb Tutorial2]] : 2e partie de la série de tutoriels, montrant l'édition, l'insertion, etc.
560-- [[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 fiche de connexion.
561-- [[SQLdb Tutorial4/fr|SQLdb Tutorial4]] : 4e partie de la série de tutoriels, montrant comment utiliser les modules de données.
562-- [[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.
563-- [[SQLdb Package/fr|Paquet SQLdb]] : Information sur le paquetage SQLdb.
564-- [[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.
565-- [[SqlDBHowto/fr|SqlDBHowto]] : Information sur l'utilisation du paquet SQLdb.
566-- [[Working With TSQLQuery/fr|Travailler avec TSQLQuery]] : Informations sur TSQLQuery.
567-- [utilisation des paramètres](http://www.freepascal.org/docs-html/fcl/sqldb/usingparams.html)
541+ * [[SQLdb Tutorial0/fr|SQLdb Tutorial0]] : Instructions pour configurer les tables et les données d'exemple pour la série de tutoriels.
542+ * [[SQLdb Tutorial1/fr|SQLdb Tutorial1]] : 1re partie de la série de tutoriels sur les bases de données, montrant comment configurer une grille pour afficher les données.
543+ * SQLdb Tutorial2 : 2e partie de la série de tutoriels, montrant l'édition, l'insertion, etc.
544+ * [[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 fiche de connexion.
545+ * [[SQLdb Tutorial4/fr|SQLdb Tutorial4]] : 4e partie de la série de tutoriels, montrant comment utiliser les modules de données.
546+ * [[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.
547+ * [[SQLdb Package/fr|Paquet SQLdb]] : Information sur le paquetage SQLdb.
548+ * [[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.
549+ * [[SqlDBHowto/fr|SqlDBHowto]] : Information sur l'utilisation du paquet SQLdb.
550+ * [[Working With TSQLQuery/fr|Travailler avec TSQLQuery]] : Informations sur TSQLQuery.
551+ * [utilisation des paramètres](<http://www.freepascal.org/docs-html/fcl/sqldb/usingparams.html>)
568552
569553---
570-*From the Free Pascal wiki, page "SQLdb Tutorial2/fr", as it stood on 2020-02-26 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
554+*From the Free Pascal wiki, page "SQLdb Tutorial2/fr", as the Internet Archive kept it on 2025-02-19, last changed on 2020-02-27. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history