IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Utiliser le modèle ADOX avec Visual Basic

Utiliser le modèle ADOX avec Visual Basic


précédentsommairesuivant

IX. L'objet Table

Cet objet représente une table de la base de données. Les tables de type "VIEW" seront vues dans le chapitre du même nom. Nous allons donc regarder les tables Standard.

Une table contient des champs (colonnes), des index, des clés et des propriétés propres au fournisseur.

Seules deux propriétés intéressantes sont statiques : "Name" qui représente le nom de la table et est obligatoire, et "type" qui porte bien son nom mais qui est en lecture seule. Ceci fait qu'il n'y a pas de questions existentielles à se poser, lorsqu'on crée une table avec ADOX, elle est forcément standard.

La table n'existe réellement dans la base de données que lorsque

  • Son catalogue est défini
  • Elle est ajoutée à la collection Tables.

Il convient donc de créer entièrement la table avant de l'ajouter à la collection.

IX-A. Collection Properties

Cette collection n'est utilisée que dans le cas des tables liées. N'essayez pas de créer des tables liées en partant du catalogue de votre base, bien que techniquement possible cela n'est pas conseillé. Le code suivant crée une table liée

 
Sélectionnez
Sub CreateAttachedJetTable()
Dim Catalogue As ADOX.Catalog, MaTable As ADOX.Table
	Set Catalogue = New ADOX.Catalog
	Catalogue.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=D:\ADOX\baseheb.mdb;Jet OLEDB:System database=" & "D:\ADOX\system.mdw;User Id=Admin; Password="
	Set MaTable = New ADOX.Table
	MaTable.Name = "auteurs"
	Set MaTable.ParentCatalog = Catalogue
	MaTable.Properties("Jet OLEDB:Create Link") = True
	MaTable.Properties("Jet OLEDB:Link Datasource") = "D:\adox\Biblio.mdb"
	MaTable.Properties("Jet OLEDB:Link Provider String") = ";Pwd=password"
	MaTable.Properties("Jet OLEDB:Remote Table Name") = "auteurs"
	Catalogue.Tables.Append MaTable
	Set Catalogue = Nothing
End Sub

Lorsque j'écris que c'est déconseillé, ce n'est pas dû à la complexité du code mais pour les deux raisons suivantes :

  • Il faut s'assurer que le fournisseur utilisé pour faire la liaison sera présent sur le poste qui exécute.
  • Il faut bien savoir si les paramètres de sécurité de liaison seront ou ne seront pas stockés de façon permanente dans la base.

Regardons ce code. Après avoir défini un catalogue nous créons un objet Table. Dans cet exemple, le nom est le même que le vrai nom de la table dans l'autre base, mais cela n'a aucune importance. Ensuite je lui attribue un catalogue afin de pouvoir valoriser ses propriétés dynamiques. Notez bien que j'utilise l'objet Catalog de ma base car je crée une table liée dans ma base.

Je valorise ensuite mes propriétés dynamiques, notons que je ne mets pas de fournisseur dans "Jet OLEDB:Link Provider String" car je continue d'utiliser Jet mais je pourrais tout à fait changer le fournisseur. Enfin j'ajoute ma table à la collection. A partir de cet ajout, la table liée est créée mais un certain nombre de ses propriétés sont passées en lecture seule.

IX-B. Collection Columns

Il existe des collections/objets Column pour l'objet Table, Index et Key. Attention de ne pas les confondre.

La collection Columns regroupe les champs de la table. Elle possède les propriétés/méthodes d'une collection normale.

Append (méth.) : De la forme

Columns.Append Column [, Type] [, DefinedSize]

Où Column est l'objet colonne à ajouter.

IX-B-1. Objet Column

Représente dans ce cas un champ de la table. A ne pas confondre avec l'objet Column de l'index. Cet objet n'a pas de méthode.

Propriétés

Attributes

Défini si la colonne est de longueur fixe et si elle accepte les valeurs NULL.

DefinedSize

Défini la taille maximum du champ

Name

Nom de la table. Obligatoire. L'unicité d'un nom dans une collection n'est pas obligatoire, mais dans une même base, il peut pas y avoir deux tables portant le même nom.

NumericScale

A ne pas confondre avec la propriété Précision. Donne l'échelle (nombre de chiffre après la virgule) d'un champ dont le type est adNumeric ou adDecimal.

ParentCatalog

Qu'on ne présente plus!

Precision

Défini la précision (nombre maximal de chiffre pour représenter la valeur)d'un champ numérique.

Type

Défini le type du champ. Il existe beaucoup de types définis (39) mais le tableau suivant vous donnera les principaux types Access.

Type Valeur Commentaire
adSmallInt 2 Type Entier court
adInteger 3 Type Entier long (Access)
adSingle 4 Valeur décimale à simple précision
adDouble 5 Valeur décimale à double précision
adCurrency 6 Type monétaire. Utilise normalement 4 chiffres après la virgule
adDate 7 Stocké comme un double. La partie entière étant le nombre de jours depuis le 30/12/1899
adBoolean 11 Booléen
adUnsignedTinyInt 17 Numérique de type Octet
adGUID 72 Par exemple numéro de réplication
adVarWChar 202 Chaîne de caractères (type Text Access)
adLongVarWChar 203 Champs mémo (Access) et lien hypertexte
adLongVarBinary 205 Type OLE Object Access

Collection Properties

Les propriétés dynamiques de l'objet Column intéressantes sont :

Autoincrement : Permet de créer les colonnes à numérotation automatique.

Default : Définit la valeur par défaut d'un champ.

Nullable : Définit si la colonne accepte des valeurs NULL.

Fixed Length : Définit si la colonne est de longueur fixe.

Seed : Détermine la prochaine valeur qui sera fourni par un champ de type numéro Automatique.

Increment : Définit le pas d'incrément d'un champ NuméroAuto.

Jet OLEDB:Column Validation Text : Définit le message d'alerte si une règle de validation n'est pas respectée.

Jet OLEDB:Column Validation Rule : Définit une règle de validation pour un champ.

Jet OLEDB:Allow Zero Length : Définit si les chaînes vides sont autorisées.

Exemple

Dans l'exemple suivant, nous allons créer une table contenant trois champs, Identification de type NuméroAuto, Nom de type Texte, Ntel de type numérique formaté.

 
Sélectionnez
Dim Catalogue As ADOX.Catalog, MaTable As ADOX.Table
Dim strConn As String, compteur As Long, MaCol As ADOX.Column
	Set Catalogue = New ADOX.Catalog
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & "D:\User\jmarc\tutorial\ADOX\Test\NouvBase1.mdb"
	Catalogue.Create strConn
	Set MaTable = New ADOX.Table
	MaTable.Name = "PremTable"
	For compteur = 1 To 3
		Set MaCol = New ADOX.Column
		With MaCol
			.DefinedSize = Choose(compteur, 0, 50, 14)
			.Name = Choose(compteur, "Id", "Nom", "Tel")
			.Type = Choose(compteur, adInteger, adVarWChar, adVarWChar)
			.Attributes = Choose(compteur, 0, adColFixed, adColFixed + adColNullable)
			If compteur = 1 Then
				Set .ParentCatalog = Catalogue
				MaCol.Properties("Autoincrement") = True
				MaCol.Properties("Seed") = CLng(1)
				MaCol.Properties("Increment") = CLng(1)
			End If
		End With
		MaTable.Columns.Append MaCol
		Set MaCol=Nothing
	Next compteur
	Catalogue.Tables.Append MaTable
End Sub

Je commence donc par créer la base de données. Pour cela j'utilise une chaîne de connexion qui est obligatoire pour pouvoir utiliser la méthode Create de catalogue. Dans cet exemple, je ne définis pas de fichier de sécurité. Ensuite je crée mon objet Table. Comme je n'utilise pas sa collection Properties, je ne valorise pas sa propriété ParentCatalog.

Dans la boucle, je crée mes colonnes. J'utilise la fonction Choose afin d'écrire de façon plus concise. Pour chaque colonne je définis une taille, un nom, un type et éventuellement ses attributs. Notons que comme la colonne n'est pas encore ajoutée à la collection Columns, elle n'existe pas encore. Dès lors, l'ordre de valorisation des propriétés n'a aucune importance. Dans le cas de la colonne "Id" je vais créer un champ NuméroAuto. Pour cela, je dois valoriser des propriétés dynamiques, donc je dois définir la propriété ParentCatalog. Enfin j'ajoute la colonne à la collection Columns puis la table à la collection Tables.

Notez aussi que tous ce code revient au même, à l'exception de la création de la base que la commande DDL

 
Sélectionnez
CREATE TABLE PremTable(Id COUNTER, Nom TEXT 50 NOT NULL, Tel TEXT 14)

IX-C. Collection Indexes

Représente les index de la table. Faites bien attention à ne pas confondre index et clé. Un index sert à augmenter l'efficacité du SGBDR lors des recherches, de la mise en relation etc....

Normalement devrait toujours être indexés

  • Les colonnes composantes d'une clé
  • Les colonnes ayant des contraintes de validité ou d'unicité
  • Les colonnes étant la cible de nombreuses recherches.

Les propriétés/méthodes de cette collection sont celles des collections standard si ce n'est :

Append

De la forme : Indexes.Append Index [, Columns]

Où Columns renvoie le ou les noms des colonnes devant être indexées. En général, on définit l'objet colonnes avant son ajout à la collection

IX-C-1. Objet Index

Cet objet n'a pas de méthodes.

Attention, on ne peut utiliser un objet Column avec cet objet que si la colonne appartient déjà à la collection Columns de l'objet Table.

Clustered

Indique si l'index est regroupé. Un index regroupé signifie qu'il existe un ordre physique pour les données. C'est en général l'index de la clé primaire.

IndexNulls

Définit le comportement de l'index vis à vis des colonnes ayant une valeur NULL.

PrimaryKey

Précise si l'index représente la clé primaire de la table.

NB : C'est là que je vous disais de faire attention. Une clé primaire (ou non d'ailleurs) est définie par la collection Keys. Néanmoins on définit en général aussi un index sur la colonne de clé primaire. En mettant à vrai cette propriété, la création de l'index implique la création de la clé. Donc si vous créez une clé primaire de façon implicite n'essayez pas de la recréer après dans la collection Keys et vice versa.

Unique

Définit la contrainte d'unicité.

Collection Properties

Comme toujours, la propriété ParentCatalog de l'index doit être valorisé avant l'appel d'un membre de cette collection. La plupart de ces propriétés étant en lecture seule ou redondante avec les propriétés statiques de l'objet, nous n'irons pas plus avant dans notre exploration.

Collection Columns et objet Column

Définit les colonnes sur lesquelles porte l'index. N'oubliez pas qu'un index porte sur un ou plusieurs champs mais qu'il appartient à l'objet Table.

L'objet Column doit impérativement exister dans la table avant de pouvoir être ajouter à la collection Columns de l'index.

Les colonnes des index utilisent une propriété supplémentaire

SortOrder

Définit l'ordre de tri d'une colonne d'index.

Exemple

Dans mon exemple précédent je vais rajouter un index sur la colonne Nom, avec un tri croissant.

 
Sélectionnez
Set MonIndex = New ADOX.Index
With MonIndex
	.IndexNulls = adIndexNullsDisallow
	.Name = "ind1"
	.Columns.Append "Nom"
	.Columns("Nom").SortOrder = adSortAscending
End With
MaTable.Indexes.Append MonIndex

Ce code se situe après l'ajout des colonnes à l'objet Tables mais avant l'ajout de l'objet Table. Comme précédemment, je manipule mon objet avant son ajout à la collection.

Seules les colonnes indexées supportent l'emploi de la méthode de recherche Seek du recordset ADO. Celle ci est beaucoup plus performante que la méthode Find.

IX-D. Collection Keys

Nous allons aborder maintenant un des passages un peu "sensibles" de la programmation ADOX, c'est à dire les clés. Les clés sont le fondement de l'intégrité référentielle il convient de bien connaître le sujet avant de se lancer dans leur programmation. Normalement, vous avez travaillé sur le modèle de données avant de construire votre base donc il suffira de suivre celui-ci.

IX-D-1. Quelques notions

Les clés sont parfois appelées, improprement d'ailleurs, contraintes. Ceci vient du fait qu'en SQL, Primary Key est une contrainte. Pourtant si les clés peuvent être des contraintes, toutes les contraintes ne sont pas des clés.

Clé primaire

Cette clé devrait être composée d'une seule colonne mais ce n'est pas une obligation. Elle sert à identifier chaque enregistrement de manière unique. La clé primaire n'accepte pas les valeurs NULL. Beaucoup de gens utilisent un champ à numérotation automatique pour définir la clé primaire, cela n'est en rien obligatoire. Une table n'a qu'une clé primaire.

Clé étrangère

Champ de même type/sous-type de données que la clé primaire, qu'elle référence dans la table enfant. Une table peut posséder plusieurs clés étrangères.

Intégrité référentielle

Mécanisme de vérification qui s'assure que, pour chaque valeur de clé étrangère, il y a une valeur de clé primaire lui correspondant. Ce mécanisme se déclenche lors de l'ajout d'une nouvelle valeur de clé étrangère, lors de la suppression d'une clé primaire ou lors de la modification de l'une quelconque des deux clés.

Opération en cascade

Mode opératoire dépendant de l'intégrité référentielle. Celui-ci détermine éventuellement le comportement du SGBDR en cas de suppression/modification d'un enregistrement parent.

IX-D-2. Méthode Append

De la forme Keys.Append Key [, KeyType] [, Column] [, RelatedTable]

Nous examinerons plus tard le détail des paramètres (dans les propriétés de l'objet Key).

IX-D-3. Objet Key

Représente une clé primaire, étrangère ou unique.

DeleteRule

Définit les règles à appliquer lors de la suppression d'une valeur de la clé primaire. On distingue 4 cas :

AdRINone

Aucune action (équivalent du mode de gestion SQL ON DELETE NO ACTION). Cette valeur interdit toute suppression d'un enregistrement tant qu'il existe un enregistrement dépendant dans la base.

AdRICascade

Modifications en cascade (SQL ON DELETE CASCADE). Attention à l'utilisation de cette valeur. Elle supprime tous les enregistrements liés lors de la suppression de l'enregistrement père. Ceci peut être très coûteux pour le SGBD en termes de performances et doit être limité au sein d'une transaction

AdRISetNull & adRISetDefault

Attribue la valeur nulle ou la valeur par défaut à la clé étrangère. Ceci se justifie rarement sauf pour gérer des traitements par lots à posteriori.

Name

Tel que son nom l'indique

RelatedTable

Si la clé est une clé étrangère, définit le nom de la table contenant la clé primaire correspondante.

Type

Détermine s'il s'agit d'une clé primaire, étrangère ou unique. Une clé unique est une clé sans doublons.

UpdateRule

Equivalent pour les modifications à DeleteRule pour les mises à jour.

Attention de nombreux SGBDR n'acceptent pas toutes les règles de modification/suppression. Je vous rappelle aussi que ces règles s'appliquent sur la clé étrangère ; les définir pour la clé primaire ne sert à rien.

Collection Columns et objet Column

Définit la ou les colonne(s) appartenant à la clé. Celles-ci doivent déjà appartenir à la collection Columns de l'objet Table. L'objet Column de l'objet Key utilise la propriété RelatedColumn. Celle-ci définit la colonne en relation dans la table définie par RelatedTable.

IX-D-4. Exemple

Nous allons voir maintenant un exemple de création de clé.

 
Sélectionnez
Dim Catalogue As ADOX.Catalog, MaTable As ADOX.Table, compteur As Long
Dim MaCol As ADOX.Column, MaCle As ADOX.Key, MonIndex As ADOX.Index
	Set Catalogue = New ADOX.Catalog
		'ici se trouve le code précédemment vu
	Set MaCle = New ADOX.Key
	With MaCle
		.Type = adKeyPrimary
		.Name = "ClePrim"
		.Columns.Append "Id"
	End With
	MaTable.Keys.Append MaCle
	Set MaCle = Nothing
	Catalogue.Tables.Append MaTable
	Set MaTable = New ADOX.Table
	MaTable.Name = "DeuxTable"
	For compteur = 1 To 3
	Set MaCol = New ADOX.Column
	With MaCol
		.DefinedSize = Choose(compteur, 0, 255, 0)
		.Name = Choose(compteur, "NumCle", "Local", "Responsable")
		.Type = Choose(compteur, adInteger, adVarWChar, adInteger)
		Set .ParentCatalog = Catalogue
		.Attributes = Choose(compteur, 0, adColFixed, 0)
	End With
	MaTable.Columns.Append MaCol
	Set MaCol = Nothing
Next compteur
For compteur = 1 To 2
	Set MonIndex = New ADOX.Index
	With MonIndex
		.PrimaryKey = Choose(compteur, True, False)
		.Unique = Choose(compteur, True, False)
		.IndexNulls = adIndexNullsDisallow
		.Name = Choose(compteur, "ind21", "Ind22")
		.Columns.Append Choose(compteur, "NumCle", "Responsable")
		.Columns(Choose(compteur, "NumCle", "Responsable")).SortOrder =
adSortAscending
	End With
	MaTable.Indexes.Append MonIndex
	Set MonIndex = Nothing
Next compteur
Set MaCle = Nothing
Set MaCle = New ADOX.Key
With MaCle
	.DeleteRule = adRINone
	.UpdateRule = adRINone
	.Type = adKeyForeign
	.Name = "CleEtr1"
	.RelatedTable = "PremTable"
	.Columns.Append "Responsable"
	.Columns("Responsable").RelatedColumn = "Id"
End With
MaTable.Keys.Append MaCle
Set MaCle = Nothing
Catalogue.Tables.Append MaTable
End Sub

Dans ma première table je crée une clé primaire de façon explicite. Je lui donne des règles NO ACTION. Je crée ensuite une deuxième table contenant trois champs. Le champ "NumCle" quoique n'étant pas de type NuméroAuto, doit être unique et non NULL. Le champ "Responsable" est la clé étrangère et contient la valeur du champ "Id" correspondant. Ces deux colonnes sont indexées. En jouant sur la propriété PrimaryKey de l'index, je crée implicitement la clé primaire en créant l'index. Notons que cette clé portera le même nom que l'index. Je crée ensuite ma clé étrangère et me voilà avec deux tables mises en relation.

IX-E. Conclusion sur les tables

Comme nous l'avons vu au cours de ce chapitre, le schéma de construction est assez simple. Voici les quelques règles à se rappeler :

  • On crée les tables les unes après les autres en commençant toujours par les tables parents (celles qui n'ont pas de clés étrangères)
  • On ajoute un objet à sa collection lorsqu'on l'a entièrement défini.
  • On crée les champs de la table avant de définir les index et les clés.
  • On indexe toujours les champs intervenants dans les jointures et/ou cible de recherche.
  • La définition des clés lors de la création de la base augmente la sécurité des données.

précédentsommairesuivant

Copyright © 2003 bidou. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.