Difference between revisions of "SQLdb Tutorial2/fr"

From Lazarus wiki
Jump to navigationJump to search
Line 281: Line 281:
  
 
=== Insertion de nouvelles données ===
 
=== Insertion de nouvelles données ===
If you insert new rows/records without any CUST_NO information you may have noticed that you get an error message: <tt>Field CUST_NO is required, but not supplied</tt>. This also happens if you hid the CUST_NO column, as in the previous section.
+
Si vous insérez de nouveaux enregistements/lignes sans aucune information CUST_NO, vous pouvez avoir remarqué que vous obtenez le message d'erreur : <tt>Field CUST_NO is required, but not supplied</tt>. Ceci survient aussi si vous cachez la colonne CUST_NO comme dans la section précédente.
  
The reason: Lazarus thinks that CUST_NO is required. That's not so strange, because it is a primary key and the underlying table definition in the database does say it is required.
+
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.
  
If we can instruct Lazarus that this field is not actually required, we can pass empty values (=NULL values) to the database.
+
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.
Fortunately, a query's field object has a ''Required'' property that does exactly that.
+
Heureusement, un objet champ de requête a une propriété ''Required'' qui sert exactement à cela.
  
Change the code to something like:
+
Modifiez le code en quelque chose comme :
 
<syntaxhighlight>
 
<syntaxhighlight>
 
     SQLQuery1.Open;
 
     SQLQuery1.Open;

Revision as of 21:41, 29 March 2017

English (en) français (fr) 日本語 (ja)

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

Vue d'ensemble

Si vous avez suivi le 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.

Connexion dynamique à une base de données

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.

Changeons la fiche de façon à popuvoir les spécifier : ajoutez deux 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.

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

Cosmétiquement, l'ajout de quelques étiquettes (Label) pour que les gens sachent ce qu'ils sont censés taper est utile.

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.

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.

Pour clarifier, nous allons supprimer les informations de connexion de nos composants en conception : Dans le composant TSQLConnector, retirez tout les textes des propriétés UserName, Password, DatabaseName et HostName.

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.

Ajoutez le code :

procedure TForm1.Button1Click(Sender: TObject);
begin
  SQLQuery1.Close;
  //Connection settings for Firebird/Interbase database
  //only needed when we have not yet connected:
  if not DBConnection.Connected then
  begin
    DBConnection.HostName := ServerName.Text;
    DBConnection.DatabaseName := DatabaseName.Text;
    DBConnection.Username := UserName.Text;
    DBConnection.Password := Password.Text;
    // Now we've set up our connection, visually show that
    // changes are not possibly any more
    ServerName.ReadOnly:=true;
    DatabaseName.ReadOnly:=true;
    UserName.ReadOnly:=true;
    Password.ReadOnly:=true;
  end;  
  SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
  DBConnection.Connected:= True;
  SQLTransaction1.Active:= True;
  SQLQuery1.Open;
end;

Maintenant exécutez et testez si vous êtes connectés.

SQLite, autres bases de données

Adaptez la propriété Text dans le TEdit comme demandé ; p.ex. employee.sqlite pour SQLite.

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

Le code ressemblera à quelque chose comme cela :

procedure TForm1.Button1Click(Sender: TObject);
begin
  SQLQuery1.Close;
  //Connection settings for embedded databases
  //only needed when we have not yet connected:
  if not DBConnection.Connected then
  begin
    DBConnection.DatabaseName := DatabaseName.Text;
	DBConnection.UserName := 'SYSDBA'; //Firebird embedded needs this; doesn't harm if using SQLite
    // Now we've set up our connection, visually show that
    // changes are not possibly any more
    DatabaseName.ReadOnly:=true;
  end;  
  SQLQuery1.SQL.Text:= 'select * from CUSTOMER';
  DBConnection.Connected:= True;
  SQLTransaction1.Active:= True;
  SQLQuery1.Open;
end;

Filtrage de données

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 :

select * from CUSTOMER where COUNTRY = 'USA'

... qui devrait être transformé en quelque chose comme cela dans notre code :

SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = 'USA'';

Il y a deux raisons pour lesquelles nous n'utilisaeraon pas cette ordre dans notre exemple d'application :

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 :

SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = ''USA''';

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.

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 :

SQLQuery1.SQL.Text := 'select * from CUSTOMER';

par :

SQLQuery1.SQL.Text:= 'select * from CUSTOMER where COUNTRY = :COUNTRY';

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 :

SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;

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.

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.

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 :

procedure TForm1.Button1Click(Sender: TObject);
begin
  SQLQuery1.Close;
  //Connection settings for Firebird/Interbase database
  //only needed when we have not yet connected:
  if not DBConnection.Connected then
  begin
    DBConnection.HostName := ServerName.Text;
    DBConnection.DatabaseName := DatabaseName.Text;
    DBConnection.Username := UserName.Text;
    DBConnection.Password := Password.Text;
    // Now we've set up our connection, visually show that
    // changes are not possibly any more
    ServerName.ReadOnly:=true;
    DatabaseName.ReadOnly:=true;
    UserName.ReadOnly:=true;
    Password.ReadOnly:=true;
  end; 
  // Show all records, or filter if user specified a filter criterium
  if Edit1.Text='' then
    SQLQuery1.SQL.Text := 'select * from CUSTOMER'
  else
  begin
    SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
    SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
  end;
  DBConnection.Connected:= True;
  SQLTransaction1.Active:= True;
  SQLQuery1.Open;
end;

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.

Gestion des erreurs

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.

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 :

begin
  try
    SQLQuery1.Close;
    ...
    SQLQuery1.Open;
  except
    //We could use EDatabaseError which is a general database error, but we're dealing with Firebird/Interbase, so:
    on E: EDatabaseError do
    begin
      MessageDlg('Error','A database error has occurred. Technical error message: ' + E.Message,mtError,[mbOK],0);
      Edit1.Text:='';
    end;
  end;
end;

SQLite, PostgreSQL, autres bases de données

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.

Edition des données utilisant la grille

Edition

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.

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 :

SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
SQLTransaction1.Commit; //... and commit them using the transaction.
//SQLTransaction1.Active now is false

Nous voulons garantir que toutes les éditions (insertions, mises à jour, suppressions) sont écrites dans la base de données :

  • quand l'utilisateur change le critère de filtrage et presse le bouton poutr interroger la base de données.
  • quand la fiche est fermée.

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 :

  TForm1 = class(TForm)
    Button1: TButton;
    Datasource1: TDatasource;
    DBGrid1: TDBGrid;
    Edit1: TEdit;
    DBConnection: TIBConnection;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
*****insert the empty line here****
    procedure Button1click(Sender: TObject);
    procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
  private

puis tapez :

    procedure SaveChanges;

pressez shift-ctrl-c (combinaison par défaut) pour laisser la complétion de code créer le corps de la procédure correspondante.

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 :

procedure Tform1.SaveChanges;
// Saves edits done by user, if any.
begin
  try
    if SQLTransaction1.Active then
    // Only if we are within a started transaction;
    // otherwise you get "Operation cannot be performed on an inactive dataset"
    begin
      SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
      SQLTransaction1.Commit; //... and commit them using the transaction.
      //SQLTransaction1.Active now is false
    end;
  except
  on E: EDatabaseError do
    begin
      MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
        E.Message, mtError, [mbOK], 0);
      Edit1.Text := '';
    end;
  end;
end;

Maintenant nous avons besoin d'appeler cette procédure aux moments appropriés :

procedure Tform1.Button1click(Sender: TObject);
begin
  SaveChanges; //Saves changes and commits transaction
  try
    SQLQuery1.Close;
....

et

procedure Tform1.Formclose(Sender: TObject; var Closeaction: Tcloseaction);
begin
  SaveChanges; //Saves changes and commits transaction
  SQLQuery1.Close;
....

Maintenant testez et voyez si les modifications réalisées dans la grille sont enregistrées dans la base de données.

Masquage de la colonne de clé primaire

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.

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.

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.

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 :

procedure Tform1.Button1click(Sender: TObject);
begin
...
    SQLQuery1.Open;
    // Hide the primary key column which is the first column in our queries.
    // We can only do this once the DBGrid has created the columns
    DBGrid1.Columns[0].Visible:=false;

Recompilez et contrôlez pour voir si la colonne de clé primaire est effectivement cachée.

SQLite, autres bases de données

  • 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.
  • Sqlite : l'exmple du dessus fonctionne pour SQLite car nous utilisons une clé primaire entière. Voir la the documentation pour des détails.

Insertion de nouvelles données

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.

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.

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.

Modifiez le code en quelque chose comme :

    SQLQuery1.Open;
    {
    Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, e.g.:
    Field CUST_NO is required, but not supplied
    We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
    when inserting new records.
    }
    SQLQuery1.FieldByName('CUST_NO').Required:=false;
    // Hide the primary key column which is the first column in our queries.
    // We can only do this once the DBGrid has created the columns
    DBGrid1.Columns[0].Visible:=false;

Suppression de données

You can let your users use the mouse to do this. You don't even need to code a single line for this functionality...

On the 'Data Controls' tab, select a TDBNavigator component and drop it on the form, above the grid.

To indicate what the navigator should be linked to, set its DataSource property to your existing datasource ('DataSource1') using the Object Inspector. Now you can use the button on the DBNavigator to delete records, but also insert them, and move around the records. Also, when editing cells/fields, you can use the Cancel button to cancel your edits.

To allow users to delete the row they're in on the grid using the Delete key, add LCLType (this contains defintions for key codes) to your uses clause:

uses
  Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
  Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;

... then handle the KeyUp event for the grid, which occurs when a key is released if in the grid. However, we do need to check that the user is not editing a field - as he'll probably use the Delete key to delete letters rather than the record he's working on.

Select the grid, then go to events and create an OnKeyUp event like this:

procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
  );
begin
  // Check for del key being hit and delete the current record in response
  // as long as we're not editing data
  if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
  begin
    //... delete current record and apply updates to db:
    SQLQuery1.Delete;
    SQLQuery1.ApplyUpdates;
  end;
end;
Light bulb  Remarque: By default TDBGrid property Options / dgDisableDelete is set to false, this means a user can delete any record with the ctrl-delete key combo. You may not want this behaviour.

Résumé

If you followed along up to now, you can retrieve data from the database, filter it, and edit and delete data in the grid. Your code should look something like this:

unit sqldbtutorial1unit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, sqldb, pqconnection, DB, FileUtil, Forms,
  Controls, Graphics, Dialogs, DBGrids, StdCtrls, DbCtrls, LCLType;
type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    DatabaseName: TEdit;
    Datasource1: TDatasource;
    DBGrid1: TDBGrid;
    Dbnavigator1: Tdbnavigator;
    Edit1: TEdit;
    Label2: Tlabel;
    Label3: Tlabel;
    Label4: Tlabel;
    Label5: Tlabel;
    Password: TEdit;
    UserName: TEdit;
    ServerName: TEdit;
    DBConnection: TIBConnection;
    Label1: TLabel;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure SaveChanges;
    procedure Button1click(Sender: TObject);
    procedure Formclose(Sender: TObject; var Closeaction: Tcloseaction);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure Tform1.Savechanges;
// Saves edits done by user, if any.
begin
  try
    if SQLTransaction1.Active then
    // Only if we are within a started transaction
    // otherwise you get "Operation cannot be performed on an inactive dataset"
    begin
      SQLQuery1.ApplyUpdates; //Pass user-generated changes back to database...
      SQLTransaction1.Commit; //... and commit them using the transaction.
      //SQLTransaction1.Active now is false
    end;
  except
  on E: EDatabaseError do
    begin
      MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
        E.Message, mtError, [mbOK], 0);
      Edit1.Text := '';
    end;
  end;
end;

procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
  );
begin
  // Check for del key being hit and delete the current record in response
  // as long as we're not editing data
  if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
  begin
    //... delete current record and apply updates to db:
    SQLQuery1.Delete;
    SQLQuery1.ApplyUpdates;
  end;
end; 

procedure Tform1.Button1click(Sender: TObject);
begin
  SaveChanges; //Saves changes and commits transaction
  try
    SQLQuery1.Close;
    //Connection settings for Firebird/Interbase database
    //only needed when we have not yet connected:
    if not DBConnection.Connected then
    begin
      DBConnection.HostName := ServerName.Text;
      DBConnection.DatabaseName := DatabaseName.Text;
      DBConnection.Username := UserName.Text;
      DBConnection.Password := Password.Text;
      // Now we've set up our connection, visually show that
      // changes are not possibly any more
      ServerName.ReadOnly:=true;
      DatabaseName.ReadOnly:=true;
      UserName.ReadOnly:=true;
      Password.ReadOnly:=true;
    end;
    // Show all records, or filter if user specified a filter criterium
    if Edit1.Text='' then
      SQLQuery1.SQL.Text := 'select * from CUSTOMER'
    else
    begin
      SQLQuery1.SQL.Text := 'select * from CUSTOMER where COUNTRY = :COUNTRY';
      SQLQuery1.Params.ParamByName('COUNTRY').AsString := Edit1.Text;
    end;
    DBConnection.Connected := True;
    SQLTransaction1.Active := True; //Starts a new transaction
    SQLQuery1.Open;
    {
    Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, i.e. error message:
    "Field CUST_NO is required, but not supplied"
    We need to tell Lazarus that, while CUST_NO is a primary key, it is not required
    when inserting new records.
    }
    SQLQuery1.FieldByName('CUST_NO').Required:=false;
    {
    Hide the primary key column which is the first column in our queries.
    We can only do this once the DBGrid has created the columns
    }
    DBGrid1.Columns[0].Visible:=false;
  except
    // EDatabaseError is a general error; 
    // you could also use one for your specific db, e.g.
    // use EIBDatabaseError for Firebird/Interbase
    on E: EDatabaseError do
    begin
      MessageDlg('Error', 'A database error has occurred. Technical error message: ' +
        E.Message, mtError, [mbOK], 0);
      Edit1.Text := '';
    end;
  end;
end;

procedure Tform1.Formclose(Sender: TObject; var Closeaction: Tcloseaction);
begin
  SaveChanges; //Saves changes and commits transaction
  SQLQuery1.Close;
  SQLTransaction1.Active := False;
  DBConnection.Connected := False;
end;

end.

Base de données incorporée sans modification de code

Firebird sur Windows

A bonus for Firebird users on Windows: if you have been following this tutorial (even if you only did the basic example), you renamed the fbembed.dll embedded Firebird library to fbclient.dll. With this, Lazarus could connect to regular Firebird servers (either on another machine or on your local machine). However, you can also copy the employee.fdb database to your application directory, run the application, clear the Server name TEdit and use Firebird embedded to directly connect to the database file, without any servers set up.

This is great if you want to deploy database applications to end users, but don't want the hassle of installing servers (checking if a server is already installed, if it's the right version, having users check firewalls, etc).

See Firebird embedded for more details.

September 2011: in recent development (SVN) versions of Free Pascal, FPC tries to first load fbembed.dll, so you need not rename fbclient.dll anymore for this to work.

Firebird sur Linux/OSX/Unix

There must be a way to get this to work on Linux/OSX. See Firebird for hints and links. Updates to the wiki are welcome.

SQLite

SQLite certainly offers embedded functionality - it does not allow a client/server setup on the other hand. By following the tutorial above, you can see that switching between databases (e.g. SQLite and Firebird) is not so much work at all.

Autres bases de données

Your database might offer similar functionality. Updates of this wiki for other database systems are welcome.

Voir aussi