Delphi 6 Relationnel

Henry Cesbron Lavau

Cette page a pour but de vous aider à construire une application de base de données relationnelle avec dbExpress.

Suivez les commandes et captures d'écrans.

- Titre : Delphi 6 Relationnel

- Auteur : Henry Cesbron Lavau

- Parution : 8 mai 2001

- Mise à jour : 26 avril 2020

- Licence : Copyright ® 2001 Henry Cesbron Lavau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Ce qu'il vous faut

- III. Création des tables complémentaires

- IV. Relation mère/fille

- V. Relation lookup

- VI. Pour aller plus loin

I - Introduction

Dans dbExpress avec Delphi 6 nous avons construit un accès simple à une table unique. Nous allons maintenant aborder deux types de relations :

- la relation d'une table maître avec une table détail ;

- la relation LookUp.

II - Ce qu'il vous faut

- Delphi 6 Pro ou Entreprise.

- Delphi 6 et InterBase 6 sur CD avec la Documentation sont aussi disponibles auprès du Centre Officiel de Borland : Diffus'Log - Tél : 01 34 63 07 01.

- Il vous faut aussi l'application et le fichier MaDatabase.gdb résultant de Delphi 6 et InterBase 6, ainsi que l'application développée dans dbExpress avec Delphi 6.

III - Création des tables complémentaires

Pour la création des tables, nous utilisons les IBX qui gèrent directement InterBase.
Pour cela, complétons l'application Delphi 6 et InterBase 6 dans le but de générer les tables :
À partir de la palette, placez sur le DataModule 2 IBTable,

et modifiez les propriétés pour la table Appels

Objet

Propriété

Valeur

IBTable1

Name

IBTableAppels

IBTableAppels

Database

IBDatabase1

IBTableAppels

TableName

APPELS Ignorez messages la base est fermée

IBTableAppels

FieldDefs

cliquez sur … et tapez 5 fois sur la touche Ins

Modifier les noms des champs ainsi que leurs propriétés :

IBTableAppelsField1

Name

PK_APPELS

PK_APPELS

DataType

ftInteger

PK_APPELS

Attributes

[faRequired]

DATEAPPEL

DataType

ftDateTime

TYPEDAPPEL

DataType

ftString

TYPEDAPPEL

Size

12

RAPPELER

DataType

ftBoolean (sera traduit en SmallInt)

COUT

DataType

ftCurrency (sera traduit en Double Precision)

IBTableAppels

FieldDefs

cliquez sur … et tapez 1 fois sur la touche Ins

Modifier le nom du champ ainsi que sa propriété :

IBTableAppelsFieldIndex1

Name

PK_APPELS

PK_APPELS

Options

[ixPrimary]

et les propriétés pour la table TypesDAppel

Objet

Propriété

Valeur

IBTable1

Name

IBTableTypesDAppel

IBTableTypesDAppel

Database

IBDatabase1

IBTableTypesDAppel

TableName

TYPESDAPPEL

IBTableTypesDAppel

FieldDefs

cliquez sur … et tapez deux fois sur la touche Ins

Modifier les noms des champs ainsi que leurs propriétés :

IBTableTypesDAppelField1

Name

PK_TYPESDAPPEL

PK_TYPESDAPPEL

DataType

ftInteger

PK_TYPESDAPPEL

Attributes

[faRequired]

TYPEDAPPEL

DataType

ftString

TYPEDAPPEL

Size

12

IBTableTyoesDAppel

FieldDefs

cliquez sur … et tapez une fois sur la touche Ins

Modifier le nom du champ ainsi que sa propriété :

IBTableAppelsFieldIndex1

Name

PK_TYPESDAPPEL

PK_TYPESDAPPEL

Options

[ixPrimary]

On n'introduit pas d'autres composants, puisque notre seul but est de créer les tables.

Pour que les tables soient créées, on ajoute :

IBTableAppels.CreateTable;
IBTableTypesDAppel.CreateTable;

en fin de la méthode IBDatabase1Open.

Et on exécute une fois le programme.

Note : la création de tables à travers l'IDE comme ci-dessus ou par CREATE TABLE est une affaire de goût.
Ceux qui préfèrent CREATE TABLE, peuvent s'inspirer de Ma première base InterBase et lancer l'ordre suivant (qui n'est volontairement pas formaté pour permettre un copier/coller dans l'Interactive SQL d'IBConsole) :

CREATE TABLE "APPELS" ( "PK_APPELS" INTEGER NOT NULL, "DATEAPPEL" TIMESTAMP,
"TYPEDAPPEL" VARCHAR(12), "RAPPELER" SMALLINT, "COUT" DOUBLE PRECISION,
"PK_NOMS" INTEGER NOT NULL, CONSTRAINT "PK_APPELS" PRIMARY KEY ("PK_APPELS") );
CREATE TABLE "TYPESDAPPEL" ( "PK_TYPESDAPPEL" INTEGER NOT NULL,
"TYPEDAPPEL" VARCHAR(12), CONSTRAINT "PK_TYPESDAPPEL" PRIMARY KEY ("PK_TYPESDAPPEL") );

Les tables étant créées, nous allons maintenant voir comment Delphi prend en compte la logique relationnelle.

IV - Relation mère/fille

Pour relier la table Appels à la forme, nous créons une chaîne dbExpress identique à celle que nous avons établie dans dbExpress avec Delphi 6 pour la table Noms. Il suffit d'ailleurs d'aller sur le data module, de sélectionner l'ensemble des composants sauf SQLConnection1, et de faire un copier/coller. (Les composants viennent se coller exactement sur les composants copiés : descendez-les tous en faisant [Ctrl + Maj + Bas] avant de les désélectionner.)

Il suffit maintenant d'adapter les propriétés :

Composant

Propriété

Valeur

SQLDataSet1

Name

SQLDataSetAppels

SQLDataSetAppels

SQLConnection

SQLConnection1

SQLDataSetAppels

CommandText

select * from APPELS

DataSetProvider1

Name

DataSetProviderAppels

DataSetProviderAppels

DataSet

SQLDataSetAppels

ClientDataSet1

Name

ClientDataSetAppels

ClientDataSetAppels

ProviderName

DataSetProviderAppels

DataSource1

Name

DataSourceAppels

DataSourceAppels

DataSet

ClientDataSetAppels

Comment allons-nous indiquer la liaison mère/fille ?

Tout simplement en indiquant que ClientDataSetAppels dépend de ClientDataSetNoms à l'aide des propriétés suivantes :

Composant

Propriété

Valeur

ClientDataSetAppels

MasterSource

DataSourceNoms

ClientDataSetAppels

MasterFields

PK_NOMS (1)

ClientDataSetAppels

IndexFieldNames

PK_NOMS;DATEAPPEL

(1) Ne cliquez pas sur les … de la ligne MasterField : en le faisant, vous provoquez les choses suivantes :

- activation de la connexion SQLConnection1 ;

- chargement de FieldDefs ;

- ouverture d'une dual liste pour établir la liaison.

Évidemment, il est plus agréable d'avoir à choisir dans une liste. Mais vous pouvez souhaiter contrôler le moment de l'ouverture de la connexion à l'exécution en démarrant avec Connected à False. De plus, vous pouvez souhaiter que les champs FieldDefs du ClientDataSet soient reconstitués automatiquement à l'exécution pour refléter d'éventuelles modifications de la structure de la table. Si néanmoins vous avez affiché la dual liste, il vous suffit de :

- mettre dans l'IDE SQLConnection1.Connected à False ;

- et, toujours dans l'IDE, ClientDataSetAppels.StordeDefs à False.

Pour terminer, nous ajoutons la procédure d'ouverture de la table Appels :

procedure TDataModule1.ClientDataSetAppelsOpen;
begin
ClientDataSetAppels.Open;
end;

Sur la Forme UnitForm, nous plaçons une grille supplémentaire que nous connections à DataModule1.DataSourceAppels

Objet

Propriété

Valeur

DBGrid1

Name

DBGridAppels

et dans FormShow nous ajoutons l'ordre d'ouverture de la table Appels, ainsi que les mises à jour d'Appels :

procedure TFormNoms.FormShow(Sender: TObject);
begin
DBGridNoms.DataSource := DataModule1.DataSourceNoms;
DataModule1.ClientDataSetNomsOpen;
DBGridAppels.DataSource := DataModule1.DataSourceAppels;     DataModule1.ClientDataSetAppelsOpen;
end;

procedure TFormNoms.ButtonApplyUpdatesClick(Sender: TObject);
begin
DataModule1.ClientDataSetNoms.ApplyUpdates(-1);
DataModule1.ClientDataSetAppels.ApplyUpdates(-1);
end;

procedure TFormNoms.ButtonCancelUpdatesClick(Sender: TObject);
begin
DataModule1.ClientDataSetNoms.CancelUpdates;
DataModule1.ClientDataSetAppels.CancelUpdates;
end;

Nous exécutons et saisissons : les valeurs de liaisons des appels sont préremplies automatiquement, et la relation est totalement gérée.

Cliquez sur Sauvegarder les modifications avant de sortir de l'application.

Votre premier programme relationnel est prêt.

V - Relation lookup

Nous allons maintenant ajouter un contrôle sur la zone TypeDAppel. En effet, nous souhaitons que ce type appartienne à la table TypesDAppel que nous avons créée au début.

Nous ajoutons la connectique dbExpress de cette table. C'est maintenant une opération qui devient une habitude : il suffit de répéter ce que nous avons fait pour la table Appels pour obtenir ceci :

Vérifiez sur les composants de la rangée du bas, que vous avez bien mis TypesDAppel partout où il y avait Appels et que vous avez :

select * from TYPESDAPPEL

Créez la procédure d'ouverture :

procedure TDataModule1.ClientDataSetTypesDAppelOpen;
begin
ClientDataSetTypesDAppel.Open;
end;

Ajoutez une grille sur la forme pour saisir les types d'appels, et complétez les procédures :

procedure TFormNoms.FormShow(Sender: TObject);
begin
DBGridNoms.DataSource := DataModule1.DataSourceNoms;
DataModule1.ClientDataSetNomsOpen;
DBGridTypesDAppel.DataSource := DataModule1.DataSourceTypesDAppel;     DataModule1.ClientDataSetTypesDAppelOpen;
DBGridAppels.DataSource := DataModule1.DataSourceAppels;     DataModule1.ClientDataSetAppelsOpen;
end;

procedure TFormNoms.ButtonApplyUpdatesClick(Sender: TObject);
begin
DataModule1.ClientDataSetNoms.ApplyUpdates(-1);
DataModule1.ClientDataSetTypesDAppel.ApplyUpdates(-1);
DataModule1.ClientDataSetAppels.ApplyUpdates(-1);
end;

procedure TFormNoms.ButtonCancelUpdatesClick(Sender: TObject);
begin
DataModule1.ClientDataSetNoms.CancelUpdates;
DataModule1.ClientDataSetTypesDAppel.CancelUpdates;
DataModule1.ClientDataSetAppels.CancelUpdates;
end;

Il nous ne reste qu'à relier cette table avec le champ TypeDAppel de la table appel
Nous allons utiliser la propriété PickList associée à la colonne TypeDAppel de la table Appels.
Dans la forme nous ajoutons la procédure privée suivante :

procedure TFormNoms.SetTypesDAppelPickList;
var s: string;
begin
s := '';
with DataModule1.ClientDataSetTypesDAppel do
begin
First;
while not Eof do
begin
s := s + FieldByName('TYPEDAPPEL').AsString + #13;
Next;
end;
end;
DBGridAppels.Columns[2].PickList.Text := Copy(s, 1, Length(s) - 1);
end;

Cette procédure de rafraîchissement de la liste est activée à la fin de FormShow et de ApplyUpdates en ajoutant la ligne :

SetTypesDAppelPickList;

à la fin des procédures FormShow et ButtonAppluUpdatesClick.

Votre relation LookUp est prête pour la saisie.

VI - Pour aller plus loin

- Consultez les forums Delphi ainsi que Delphi et bases de données de www.developpez.com

- Abonnez-vous au news group Base de données (en français) (news://news.vienneinfo.org/nzn.fr.base-de-donnees).