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

Connexion ODBC

Vous pouvez commenter et donner une note à cet article : 5 commentaires Donner une note à l´article (5)

Ce tutoriel a pour but de montrer comment établir et utiliser une connexion ODBC avec MS-Access. Les points traités sont la création de sources de données ODBC (DSN), de tables liées ODBC, de requêtes SQL-Direct, et l'utilisation de recordsets DAO avec des connexions ODBC.

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Avec ce tutoriel, j'ai essayé de mettre par écrit mon expérience d'utilisateur/programmeur dans le domaine des connexions ODBC.

Par le biais d'ODBC il est possible à Access d'accéder à des données d'autres sources, telles des SGBD comme Oracle, MySQL, ou SQL Server, pour les plus connus.
On élargit ainsi le champ d'action d'une application développée avec Access en lui permettant d'accéder aux données d'un serveur de base de données.
Il suffit pour cela de disposer du pilote ODBC adéquat.

II. Qu'est-ce qu'ODBC ?

ODBC (Open DataBase Connectivity) est une interface de programmation (API) universelle, indépendante de la source de données. Le développeur utilise les mêmes fonctions de l'API ODBC quelle que soit la source de donnée ciblée. Le pilote se charge de mener à bien l'action demandée, en fonction du type de source de données.
Image non disponible
Si on se réfère à l'illustration ci-dessus, Access est l'application utilisant l'API ODBC.
En tant qu'utilisateur ou développeur Access, on se contente de désigner la source donnée, et de fournir les paramètres de connexion propres à celle-ci.
Cette tâche peut être encore plus simplifiée en utilisant le gestionnaire de sources de données ODBC de Windows.
L'ensemble des paramètres de connexion se résume à un nom : celui que l'on donne à une source de données (DSN en anglais pour Data Source Name).

III. Sources de données ODBC (DSN)

On peut définir une source de données ODBC comme un jeu de paramètres auquel on donne un nom.
Ces paramètres (variables en fonction du pilote ODBC) permettent d'établir la connexion avec la base de données ciblée.
Par la suite, dans des applications compatibles ODBC, on fait référence à ce jeu de paramètres en utilisant son nom, c'est-à-dire le nom de la source de données (data source name, abrégé en DSN).

III-A. L'administrateur de sources de données

C'est un programme utilitaire qui permet de gérer les sources de données ODBC (Création, Modification, Suppression) de l'ordinateur.

On y accède par le Panneau de configuration, dans les Outils d'administration (2000 et XP).
Image non disponible

Ou plus simplement en faisant Démarrer -> Exécuter, en tapant odbccp32.cpl, puis en cliquant sur OK.
Image non disponible

Image non disponible

Il y a principalement deux catégories de sources de données : utilisateur et système.
Les sources de données utilisateur ne sont visibles que par l'utilisateur Windows qui les a créées, tandis que les sources de données systèmes sont visibles pour tous les utilisateurs de l'ordinateur.
Les informations sont stockées dans la base de registre :

HKEY_CURRENT_USER\Software\ODBC\ODBC.INI pour les sources utilisateur
HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI pour les sources système

Les sources de données fichier (troisième catégorie), quant à elles, sont enregistrées dans un fichier.

La liste des pilotes ODBC installés se trouve dans l'onglet Pilotes ODBC

Image non disponible

III-B. Création d'une source de données

Tout d'abord il faut que le pilote ODBC correspondant au type de données que l'on veut utiliser soit installé sur le PC.

  • Sélectionner l'onglet "Source de données utilisateur" ou l'onglet "Source de données système" puis cliquer sur le bouton Ajouter.
  • Sélectionner le pilote ODBC souhaité, puis cliquer sur Terminer.
    La boîte de dialogue de configuration de la source de données dépend du pilote choisi.

    Voici un exemple avec MyODBC (pilote pour MySQL) :
    Image non disponible
    Voici un autre exemple avec SQL Server :
    Image non disponible
  • Entrer le nom de la source de données. On peut mettre ce que l'on veut sauf ces caractères interdits : [ ] { } ( ) , ; ? * = ! @ \
  • Le champ Description est un commentaire.
  • Les autres paramètres dépendent du type de données.
    Pour accéder à un serveur de base de données par exemple, il faudra fournir le nom du serveur ou son adresse IP, le nom de la base de données, le nom de l'utilisateur et son mot de passe.

III-C. Création d'une source de données en Visual Basic avec DAO

Grâce à la bibliothèque DAO, il est possible de définir une source de données utilisateur avec du code Visual Basic.
On utilise pour cela la méthode RegisterDatabase de la bibliothèque.

Vérifiez qu'il existe bien une référence à la bibliothèque DAO.
Dans l'éditeur Visual Basic, allez dans Outils->Références.
Puis, si ce n'est déjà fait, cochez Microsoft DAO x.x Object Library, où x.x est le numéro de version.
Image non disponible

Syntaxe de RegisterDatabase
Sélectionnez
DBEngine.RegisterDatabase dbname, driver, silent, attributes
arguments
dbname Nom de la source de données ODBC (DSN) à créer ou modifier
driver Nom du pilote ODBC tel qu'il apparaît l'onglet "pilotes ODBC" de l'Administrateur de sources de données ODBC
silent Valeur True/False pour indiquer si oui ou non on souhaite masquer la boîte de dialogue de configuration de la source de données du pilote ODBC.
attributes Liste d'attributs sous la forme Mot-clé=Valeur(*) séparés par des retours chariot (vbCr). Les mots-clés sont ceux écrits dans la base de registre. Ils varient en fonction du pilote ODBC.

(*) Les caractères [ ] { } ( ) , ; ? * = ! @ sont interdits. Si une valeur à passer en attribut contient l'un de ces caractères, il faut la mettre entre accolades { }.

Voici une liste des mots-clés les plus courants :

mot-clé Signification
SERVER Nom du serveur
DATABASE Nom de la base de données
UID Nom de l'utilisateur
PWD Mot de passe de l'utilisateur


Ce tableau récapitule les attributs utilisés dans les exemples, ainsi que les valeurs associées :

  MySQL SQL Server Oracle
SERVER LZ2 LZ2 TESTSVR
DATABASE test EMM  
UID Utilisateur   Utilisateur
PWD MotDePasse   MotDePasse

Exemple pour MySQL

 
Sélectionnez
Sub RegDB_mysql()
Dim strDSN As String, strAttr As String, strODBCDrv As String

' Nom de la source de données ODBC
strDSN = "ESSAI MySQL"
' Nom du pilote ODBC
strODBCDrv = "MySQL ODBC 3.51 Driver"
' Attributs
' OPTION est spécifique à MySQL dans cet exemple
strAttr = "SERVER=LZ2" & vbCr & "DATABASE=test" & vbCr & "OPTION=3" & vbCr & _
          "UID=Utilisateur" & vbCr & "PWD=MotDePasse"

DBEngine.RegisterDatabase strDSN, strODBCDrv, True, strAttr

End Sub

Exemple pour SQL Server

Selon la version et le type d'installation de SQL Server, le nom du serveur pourra prendre deux formes : NomServeur tout seul ou NomServeur\NomInstance.
J'utilise la forme sans le nom de l'instance.

Le contrôle d'accès au serveur met en oeuvre deux méthodes d'authentification : SQL Server ou Windows.
Avec l'authentification SQL Server on utilise les mots-clés UID et PWD pour établir une connexion, tandis qu'avec l'authentification Windows (Compte utilisateur Windows) on utilise le mot-clé Trusted_Connection auquel on affecte la valeur yes (UID et PWD ne sont pas utilisés).
J'utilise l'authentification SQL Server.
Il y a cependant une particularité avec le pilote ODBC pour SQL Server. Lorsque l'on crée une source de données, il n'enregistre pas le nom d'utilisateur et le mot de passe. Cela génère même une erreur, si la chaîne d'attributs contient UID et PWD.

 
Sélectionnez
Sub RegDB_sqlsvr()
Dim strDSN As String, strAttr As String, strODBCDrv As String

' Nom de la source de données ODBC
strDSN = "Essai SQLSVR"
' Nom du pilote ODBC
strODBCDrv = "SQL Server"
' Attributs
' UID et PWD ne sont pas acceptés par le pilote SQL Server
strAttr = "SERVER=LZ2" & vbCr & "DATABASE=EMM" 
' Si Serveur SQL avec authentification Windows,
' activer la ligne ci-dessous :
'strAttr = strAttr & vbCr & "Trusted_Connection=Yes"

DBEngine.RegisterDatabase strDSN, strODBCDrv, True, strAttr

End Sub

Exemple pour SQL Oracle

Le mot-clé SERVER correspond au nom d'un service réseau Oracle, également appelé alias. Celui-ci intègre les informations concernant le serveur Oracle et la base de données.
Pour cette raison, le mot-clé DATABASE n'est pas employé avec le pilote ODBC de Microsoft pour Oracle.
Dans cet exemple, TESTSVR est un alias déclaré dans le fichier tnsnames.ora (C:\oracle\ora81\network\ADMIN si "Oracle Client" a été installé dans C:\oracle\ora81)

 
Sélectionnez
TESTSVR =
    (DESCRIPTION =
        (ADDRESS_LIST =
            (ADDRESS = (COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = 172.111.111.111)(Port = 1234))
        )
    (CONNECT_DATA = (SID = PEE))
  )

Dans ce fichier tnsnames.ora, le nom du serveur (ou son adresse IP) est identifié par le mot-clé Host. La base de donnée est identifiée par SID.

Pour revenir à DAO, voici un exemple de création de DSN Oracle :

 
Sélectionnez
Sub RegDSN_ora()
Dim strDSN As String, strDriver As String, strAttr As String

' Nom de la source de données ODBC
strDSN = "ESSAI Oracle"
' Nom du pilote ODBC
strDriver = "Microsoft ODBC for Oracle"
' Attributs
' SynonymColumns est spécifique à ce pilote
strAttr = "UID=Utilisateur" & vbCr & "PWD=MotDePasse"
strAttr = strAttr & vbCr & "SERVER=TESTSVR"
strAttr = strAttr & vbCr & "SynonymColumns=0"

DBEngine.RegisterDatabase strDSN, strDriver, True, strAttr

End Sub

Les pilotes pour MySQL et Oracle inscrivent dans la base de registre le nom de l'utilisateur et le mot de passe. Ce n'est pas terrible d'un point de vue sécurité.
Il vaut mieux se contenter de fournir les informations relatives au serveur, à la base de données, plus d'éventuels paramètres optionnels spécifiques au pilote.
Le nom d'utilisateur et le mot de passe pourront être fournis ultérieurement lors de l'utilisation de la source de données ODBC.

III-D. Création d'une source de données avec l'API ODBC

Il existe une autre méthode que DAO, pour créer une source de données avec du code Visual Basic. Celle-ci fait appel à l'API ODBC. Elle offre, en outre, l'avantage de pouvoir créer les deux types de sources de données : utilisateur et système.
Pour pouvoir utiliser l'API ODBC, il faut au préalable déclarer quelques constantes et fonctions de la bibliothèque dynamique odbccp32.dll
Cela se fait en mettant du code dans la section Déclarations d'un module de code.
Cette section se situe entre le début du module et la première procédure (Sub) ou la première fonction (Function).

Illustration :
Image non disponible


Voici le code pour déclarer les constantes et les fonctions de l'API ODBC dont nous aurons besoin :

Déclarations
Sélectionnez
Public Const ODBC_ADD_DSN As Long = 1          ' Ajoute DSN utilisateur
Public Const ODBC_ADD_SYS_DSN As Long = 4      ' Ajoute DSN système

Public Const ODBC_REMOVE_DSN As Long = 3       ' Supprime DSN utilisateur
Public Const ODBC_REMOVE_SYS_DSN As Long = 6   ' Supprime DSN système

Public Declare Function SQLConfigDataSource Lib "odbccp32.dll" _
    (ByVal hWndParent As Long, ByVal fRequest As Long, _
     ByVal lpszDriver As String, ByVal lpszAttributes As String) As Long

Public Const SQL_SUCCESS As Long = 0
Public Const SQL_SUCCESS_WITH_INFO As Long = 1

Public Declare Function SQLInstallerError Lib "odbccp32.dll" _
    (ByVal iError As Integer, _
     ByRef pfErrorCode As Long, _
     ByVal lpszErrorMsg As String, _
     ByVal cbErrorMsgMax As Long, _
     ByRef pcbErrorMsg As Long) As Long

Avec la fonction SQLConfigDataSource, on va pouvoir créer ou supprimer une source de données ODBC (DSN).

arguments de SQLConfigDataSource
hWndParent Handle de fenêtre Windows ou 0 (zéro).
Par exemple Application.hWndAccessApp ou Me.Hwnd depuis un formulaire
fRequest ODBC_ADD_DSN pour ajouter un DSN utilisateur
ODBC_ADD_SYS_DSN pour ajouter un DSN système
ODBC_REMOVE_DSN pour supprimer un DSN utilisateur
ODBC_REMOVE_SYS_DSN pour supprimer un DSN système
lpszDriver Nom du pilote ODBC
lpszAttributes Liste de paramètres mot clé=valeur(*). Chaque paire mot clé/valeur est terminée par un caractère nul et la liste elle-même est terminée par un caractère nul.
On a donc en bout de chaîne deux caractères nuls.

(*) Les caractères [ ] { } ( ) , ; ? * = ! @ sont interdits. Si une valeur à passer en attribut contient l'un de ces caractères, il faut la mettre entre accolades { }.

La fonction SQLInstallerError permet de lire d'éventuelles erreurs consécutives à l'exécution de SQLConfigDataSource.

Les attributs sont les mêmes qu'avec DAO, à la différence près que le nom de la source de données (DSN) fait partie de la liste des attributs.

mot-clé Signification
DSN Nom de la source de données
SERVER Nom du serveur
DATABASE Nom de la base de données
UID Nom de l'utilisateur
PWD Mot de passe de l'utilisateur


Attributs utilisés dans les exemples qui suivent :

  MySQL Sql Server Oracle
DSN ESSAI MySQL ESSAI SQLSVR ESSAI Oracle
SERVER LZ2 LZ2 TESTSVR
DATABASE test EMM  
UID Utilisateur   Utilisateur
PWD MotDePasse   MotDePasse
Exemple d'utilisation avec MySQL
Sélectionnez
Sub apiRegDSN_mysql1()
Dim strDriver As String, strAttr As String, retVal As Long
Dim pfErrorCode As Long, pcbErrorMsg As Long, lpszErrorMsg As String, i As Integer

' Nom du pilote ODBC
strDriver = "MySQL ODBC 3.51 Driver" & vbNullChar

' Minimum fonctionnel requis
strAttr = "DSN=" & "ESSAI MySQL" & vbNullChar

' facultatif
strAttr = strAttr & "SERVER=LZ2" & vbNullChar
strAttr = strAttr & "DATABASE=test" & vbNullChar
strAttr = strAttr & "Description=ESSAI DSN MySQL" & vbNullChar
strAttr = strAttr & "OPTION=3" & vbNullChar
strAttr = strAttr & "UID=Utilisateur" & vbNullChar

' Terminaison
strAttr = strAttr & vbNullChar

retVal = SQLConfigDataSource(0, ODBC_ADD_SYS_DSN, strDriver, strAttr)

If retVal = 0 Then
   i = 0
   Do
      i = i + 1
      lpszErrorMsg = String(2048, vbNullChar)
      retVal = SQLInstallerError(i, pfErrorCode, lpszErrorMsg, 2047, pcbErrorMsg)
      If retVal = SQL_SUCCESS_WITH_INFO Then retVal = SQL_SUCCESS
      If retVal = SQL_SUCCESS Then MsgBox Left(lpszErrorMsg, pcbErrorMsg)
   Loop Until (retVal <> SQL_SUCCESS Or i = 8)
End If

End Sub

Plutôt que d'utiliser directement la fonction SQLConfigDataSource de l'API ODBC, on peut écrire une fonction un peu à la manière de celle de DAO, pour en faciliter l'utilisation.

Nous appellerons cette fonction apiRegDB.

Syntaxe
Sélectionnez
apiRegDB(strDSN, strDriver, strAttr, lngDSNtype, blnDeleteBeforeCreate) As Boolean
Arguments
strDSN Nom de la source de données ODBC (DSN) à créer ou modifier
strDriver Nom du pilote ODBC tel qu'il apparaît dans l'onglet "pilotes ODBC" de l'Administrateur de sources de données ODBC
strAttr chaîne d'attributs mot clé=valeur. Chaque paire mot-clé/valeur est terminée par un caractère nul (vbNullChar).
On ne met pas le mot clé DSN dans cette chaîne d'attributs puisqu'il est déjà transmis dans strDSN
lngDSNtype constante énumérée (voir déclaration plus bas)
dsnUser : source de données Utilisateur
dsnSystem : source de données Système
blnDeleteBeforeCreate True : supprime la source de données avant de la créer


Ajouter dans la section Déclarations, cette déclaration du type énuméré dsnTypes :

apiRegDB
Sélectionnez
Public Enum dsnTypes
        dsnUser = 0
        dsnSystem = 1
End Enum


Code de la fonction :

 
Sélectionnez
' ---------------------------------------------------------
' Function apiRegDB
' ---------------------------------------------------------
' Entrée:
' ======
' strDSN .............. : Nom de la source de données à créer
' strDriver ........... : Nom du pilote ODBC
' strAttributes ....... : Paramètres
' lngDSNtype .......... : dsnUser   -> crée DSN utilisateur 
'                         dsnSystem -> crée DSN système
' blnDeleteBeforeCreate : True  -> supprime DSN avant création
'
' Retourne:
' ========
' True si succès, sinon False
' ---------------------------------------------------------
Function apiRegDB(strDSN As String, strDriver As String, strAttributes As String, _
                  Optional lngDSNtype As dsnTypes = dsnTypes.dsnUser, _
                  Optional blnDeleteBeforeCreate As Boolean = False) As Boolean
Dim retVal As Long, strAttr As String, strErrMsg As String
Dim Add_DSN As Long, Rmv_DSN As Long
Dim pfErrorCode As Long, pcbErrorMsg As Long, lpszErrorMsg As String, i As Integer

If lngDSNtype = dsnSystem Then
   ' Source de données système
   Add_DSN = ODBC_ADD_SYS_DSN
   Rmv_DSN = ODBC_REMOVE_SYS_DSN
Else
   ' Source de données utilisateur
   Add_DSN = ODBC_ADD_DSN
   Rmv_DSN = ODBC_REMOVE_DSN
End If

If blnDeleteBeforeCreate Then
   ' Supprime source de données si déjà créée
   strAttr = "DSN=" & strDSN & vbNullChar & vbNullChar
   retVal = SQLConfigDataSource(0, Rmv_DSN, strDriver, strAttr)
End If

' Construit chaîne d'attributs mot-clé=valeur
' Chaque paire mot-clé/valeur est terminée par un caractère nul
strAttr = "DSN=" & strDSN & vbNullChar
strAttr = strAttr & strAttributes
' Terminaison de la chaîne
strAttr = strAttr & vbNullChar

' Crée source de données
retVal = SQLConfigDataSource(0, Add_DSN, strDriver, strAttr)

If retVal = 0 Then
   i = 0
   Do
      i = i + 1
      lpszErrorMsg = String(2048, vbNullChar)
      retVal = SQLInstallerError(i, pfErrorCode, lpszErrorMsg, 2047, pcbErrorMsg)
      If retVal = SQL_SUCCESS_WITH_INFO Then retVal = SQL_SUCCESS
      If retVal = SQL_SUCCESS Then
         If Len(strErrMsg) > 0 Then strErrMsg = strErrMsg & vbCrLf & vbCrLf
         strErrMsg = strErrMsg & Left(lpszErrorMsg, pcbErrorMsg)
      End If
   Loop Until (retVal <> SQL_SUCCESS Or i = 8)
   MsgBox strErrMsg, , "SQLConfigDataSource"
   apiRegDB = False
Else
   apiRegDB = True
End If

End Function


Voici maintenant des exemples illustrant l'utilisation de la fonction apiRegDB :

Exemple pour MySQL
Sélectionnez
Sub apiRegDSN_mysql2()
Dim strDSN As String, strAttr As String, strODBCDrv As String
Dim blnSuccess As Boolean

' Nom de la source de données ODBC
strDSN = "ESSAI MySQL"
' Nom du pilote ODBC
strODBCDrv = "MySQL ODBC 3.51 Driver"
' Attributs
strAttr = "SERVER=LZ2" & vbNullChar & "DATABASE=test" & vbNullChar
strAttr = strAttr & "Description=ESSAI DSN MySQL" & vbNullChar
strAttr = strAttr & "OPTION=3" & vbNullChar
strAttr = strAttr & "UID=Utilisateur" & vbNullChar

blnSuccess = apiRegDB(strDSN, strODBCDrv, strAttr, dsnSystem, True)

End Sub
Exemple pour SQL Server
Sélectionnez
Sub apiRegDSN_sqlserver2()
Dim strDSN As String, strAttr As String, strODBCDrv As String
Dim blnSuccess As Boolean

' Nom de la source de données ODBC
strDSN = "ESSAI SQLSVR"
' Nom du pilote ODBC
strODBCDrv = "SQL Server"
' Attributs
strAttr = "SERVER=LZ2" & vbNullChar & "DATABASE=EMM" & vbNullChar & _
          "Description=ESSAI DSN SQL Server" & vbNullChar

blnSuccess = apiRegDB(strDSN, strODBCDrv, strAttr, dsnSystem, True)

End Sub
Exemple pour Oracle
Sélectionnez
Sub apiRegDSN_oracle2()
Dim strDSN As String, strAttr As String, strODBCDrv As String
Dim blnSuccess As Boolean

' Nom de la source de données ODBC
strDSN = "ESSAI Oracle"
' Nom du pilote ODBC
strODBCDrv = "Microsoft ODBC for Oracle"
' Attributs
strAttr = "SERVER=TESTSVR" & vbNullChar & "UID=Utilisateur" & vbNullChar
strAttr = strAttr & "Description=" & "ESSAI DSN Oracle" & vbNullChar

blnSuccess = apiRegDB(strDSN, strODBCDrv, strAttr, dsnSystem, True)

End Sub

III-E. Au final

En résumé, on peut créer une source de données ODBC :

  • Manuellement avec l'administrateur de sources données ODBC
  • Par code avec DAO, mais la source est de type utilisateur, uniquement visible de celui qui l'a créée.
  • Par code avec l'API ODBC.

IV. Utilisation d'une source de données ODBC pour lier une table

Le principal intérêt d'ODBC dans Access est de pouvoir lier des tables ou des vues d'un autre système de base de données.
Une fois créées, ces tables liées s'utilisent comme des tables Access, avec certaines restrictions en fonction du pilote ODBC.

Convention sur le vocabulaire utilisé dans ce tutoriel :
"Table liée" désigne une table Access qui pointe vers une autre table.
"Table Source" désigne la table externe, à laquelle une table liée fait référence.
Une "Table liée" est donc une sorte de raccourci vers une autre table, "la table source".

Image non disponible

Dans l'illustration ci-dessus, la table Access Clients est une table liée ODBC qui fait référence à la table Clients du SGBD.
Lorsqu'on ouvre la table liée, Access va lire les données de la table source au travers d'une liaison ODBC et affiche les enregistrements dans une feuille de données, comme s'il s'agissait d'une table Access locale.
La liaison ODBC est totalement transparente.

IV-A. Par l'intermédiaire du menu d'Access

Le procédé pour lier une table ODBC est le même que pour lier une table d'une autre base de données Access, ou encore une feuille Excel.

Sauf indication, le cheminement à travers les menus et les captures d'écran qui suivent correspondent à Access 2000~2003

Menu->Fichiers->Données Externes->Lier les tables... :
Image non disponible

Choisir type de fichiers "ODBC Databases ()" :
Image non disponible

Pour Access 2007 :
Données externes->Importer->Plus->Base de données ODBC
Image non disponible

Puis, dans la fenêtre qui s'ouvre, sélectionner : Lier à la source de données en créant une table attachée

Choisir le nom de la source de données :
Image non disponible

Si le driver n'a pas suffisamment d'informations pour établir la connexion, il ouvre une boîte de dialogue.
Par exemple ici il faut fournir un mot de passe :
Image non disponible

Choisir la ou les tables :
Image non disponible
Access peut enregistrer le mot de passe de manière à ce qu'il ne vous soit plus demandé par la suite.
C'est le seul moment où l'on peut choisir cette option.
Si le mot de passe n'est pas enregistré, une boîte de dialogue du pilote ODBC le demandera lorsqu'on voudra accéder aux données de la table liée.
Il n'est demandé qu'une fois pour la source de données pendant la durée de la session Access.

Pour chaque table à attacher (lier) n'ayant pas de clé et pas d'index unique, Access demande quels sont les champs à utiliser pour créer une clé (en local dans la base de données Access).
Image non disponible
Les données d'une table liée ODBC sans clé ne peuvent pas être modifiées par Access.
Autrement dit, une table liée sans clé est une table en lecture seule.
A l'inverse, les données d'une table liée ODBC avec clé peuvent être modifiées, sous réserve que l'utilisateur dispose de droits suffisants.

Les tables liées ODBC sont représentées dans Access par cet icône Image non disponible (Image non disponible dans Access 2007).

IV-B. Par code VBA

On peut créer une table liée ODBC avec la méthode TransferDatabase d'Access ou avec la bibliothèque DAO.
Dans les deux cas nous aurons besoin d'une chaîne de connexion ODBC.
Cette chaîne de connexion commence obligatoirement par "ODBC;" dans Access.
Viennent ensuite des paires mot-clé/valeur, séparés par des points-virgules.

 
Sélectionnez
ODBC;mot-clé1=valeur1;mot-clé2=valeur2;...;mot-cléi=valeuri

Rappel : si une valeur à passer en attribut contient un de ces caractères interdits [ ] { } ( ) , ; ? * = ! @ , il faut la mettre entre accolades { }

Les mots-clés les plus courants sont ceux que nous avons déjà vus précédemment :

mot-clé Signification
DSN Nom de la source de données
SERVER Nom du serveur
DATABASE Nom de la base de données
UID Nom de l'utilisateur
PWD Mot de passe de l'utilisateur

Si le nom du serveur et/ou le nom de la base de données sont déjà définis dans la source de données (DSN), on peut les omettre

IV-B-1. Avec TransferDatabase

Syntaxe de la commande TransferDatabase
Sélectionnez
DoCmd.TransferDatabase typetransfert, typebase, nombase, typeobjet, source, destination, structureseulement, enregcodeconnexion
typetransfert acLink pour créer un lien
typebase "Base de données ODBC"
nombase chaîne de connexion ODBC "ODBC;..."
typeobjet acTable
source Nom de la table dans la base de données ODBC
destination Nom de la table dans Access
structureseulement False
enregcodeconnexion True : enregistre le nom d'utilisateur et le mot de passe pour la connexion ODBC

Exemple
On lie la table MySQL fournisseurs2 et elle s'appellera mysql_fournisseurs2 dans Access.
Par conséquent

  • table liée = mysql_fournisseurs2
  • table source = fournisseurs2

On suppose que la source de donnée "ESSAI MySQL" contient déjà les définitions du serveur et de la base de données.
Il est donc inutile de les mettre dans la chaîne de connexion.

Exemple TransferDatabase
Sélectionnez
Dim strConn As String

strConn = "ODBC;" & _
          "DSN=ESSAI MySQL;" & _
          "UID=Utilisateur;PWD=MotDePasse"
          
DoCmd.TransferDatabase acLink, "Base de données ODBC", strConn, _
      acTable, "fournisseurs2", "mysql_fournisseurs2", , True

La table fournisseurs2 n'ayant ni clé ni index unique, Access ouvre la boîte de dialogue invitant l'utilisateur à sélectionner un ou plusieurs champs de manière à créer un identifiant unique d'enregistrement.
Image non disponible Si on n'indique pas d'identifiant unique, la table sera en lecture seule.

IV-B-2. Avec la bibliothèque DAO

Principe :
On crée une nouvelle définition de table (objet TableDef).
Le nom qu'on lui donne sera celui de la table liée dans Access.

On renseigne les propriétés Connect et SourceTableName de l'objet TableDef.

Connect chaîne de connexion ODBC "ODBC;..."
(la même que celle utilisée avec TransferDatabase)
SourceTableName Nom de la table dans la base de données ODBC

Si on veut qu'Access sauvegarde le nom d'utilisateur et le mot de passe on ajoute l'attribut dbAttachSavePWD à la propriété Attributes de l'objet TableDef.

Enfin, on ajoute la nouvelle définition de table à la collection TableDefs de la base de données Access :

Exemple DAO
Sélectionnez
Dim strConn As String, db As DAO.Database, td As DAO.TableDef 

Set db = CurrentDb
'  Chaîne de connexion
strConn = "ODBC;" & _
          "DSN=ESSAI MySQL;" & _
          "UID=Utilisateur;PWD=MotDePasse"
' Création nouvelle définition de table
Set td = db.CreateTableDef("mysql_fournisseurs2")
' Optionnel : Sauver mot de passe
td.Attributes = td.Attributes Or dbAttachSavePWD
' Chaîne de connexion ODBC pour DAO
td.Connect = strConn
' Nom de la table source
td.SourceTableName = "fournisseurs2"
' Ajouter à la collection
db.TableDefs.Append td

Set td = Nothing
set db=Nothing
' Actualiser fenêtre base de données pour que la nouvelle table apparaisse
Application.RefreshDatabaseWindow

Contrairement à TransferDatabase, la méthode DAO ne demande pas à l'utilisateur de sélectionner le ou les champs formant un identificateur unique d'enregistrement.
Il faut donc ajouter un index par code.
Ce n'est pas possible avec DAO : on ne peut pas ajouter d'index à une définition de table liée.
On va donc le faire avec une instruction SQL de création d'index.

 
Sélectionnez
CREATE UNIQUE INDEX nom_index
ON nom_table (champ1 ASC [,champ2 ASC,..., champi ASC]) WITH PRIMARY

Voir CREATE INDEX sur office.microsoft.com

En VBA, pour l'exemple précédent, cela donne ceci :

 
Sélectionnez
Dim db As DAO.Database, strIndex As String
Set db = CurrentDb

' Ajout index clé primaire
strIndex = "CREATE UNIQUE INDEX __uniqueindex " & _
           "ON  mysql_fournisseurs2 ([N° fournisseur] ASC) WITH PRIMARY"
db.Execute strIndex, dbFailOnError

Si la table de la base de données ODBC possède une clé ou un index unique il n'y a (sauf exception) pas de problème, car Access et DAO créent automatiquement la clé en local dans la base Access.

V. Modification d'une table liée ODBC

Dans le chapitre précédent nous avons vu comment créer une table liée ODBC, soit à l'aide du menu Access, soit par code Visual Basic.
Nous allons maintenant voir comment modifier une table liée (les caractéristiques du lien).
Cela peut s'avérer utilise s'il faut modifier un des attributs de la chaîne de connexion.

V-A. Par l'intermédiaire du menu d'Access

Comme avec une table liée Access, on utilise le gestionnaire de tables liées.
Outils > Utilitaires de base de données > Gestionnaire de tables liées :
Image non disponible

Si on ne coche pas "Toujours demander un nouvel emplacement", la table liée est recrée sans poser de question (si le DSN est toujours valide).
Dans le cas contraire (DSN non valide), la boîte de dialogue du pilote ODBC est ouverte.
Si on ferme cette boîte de dialogue sans qu'une connexion puisse être établie, Access nous invite à sélectionner une source de données ODBC.

Si on coche "Toujours demander un nouvel emplacement", Access nous invite à re-sélectionner une source de données ODBC.
La table liée est recréée.

Dans les deux cas on ne peut pas changer le nom de la table source, c'est à dire celle se trouvant dans la base de données référencée par le DSN.

V-B. Par code VBA

Nous retrouvons les deux techniques VBA déjà utilisée, TransferDatabase et DAO.

V-B-1. Avec TransferDatabase

TransferDatabase ne permet pas de modifier directement une table liée ; il faut donc la détruire, puis la recréer.

V-B-2. Avec la bibliothèque DAO

Avec DAO, on peut modifier la propriété Connect de l'objet TableDef, mais pas la propriété SourceTable.
Par exemple, la table liée mysql_fournisseurs2 créée un peu plus tôt a pour table source la table fournisseurs2
Si on veut changer le nom de la table source il faudra détruire la table liée mysql_fournisseurs2 et la recréer.

En revanche, on peut modifier ce que l'on veut dans la propriété Connect.
Le changement prend effet après appel de méthode RefreshLink de l'objet TableDef.
Cette méthode recrée la table liée si bien que l'on perd l'index unique si on en avait créé un.
Il faut penser à le recréer si cela se produit.

Dans cet exemple, on va changer le nom d'utilisateur (UID) et le mot de passe (PWD).

 
Sélectionnez
Sub ChgODBClink_DAO2()
Dim strConn As String, db As DAO.Database, td As DAO.TableDef
Dim strParts() As String, i As Integer
Dim strTable As String, strUID As String, strPWD As String
Dim errX As DAO.Error, strErrMsg As String
Dim strCreateIdx As String, strUniqueRecord  As String

strTable = "mysql_fournisseurs2"
strUniqueRecord = "[N° fournisseur] ASC"
strUID = "NvUtilisateur"
strPWD = "NvMotDePasse"

Set db = CurrentDb
On Error Resume Next
Set td = db.TableDefs(strTable)
On Error GoTo 0
If td Is Nothing Then
   strErrMsg = "La Table '" & strTable & "' est introuvable"
   GoTo QUIT
End If

' Si la table est bien une table liée ODBC
If td.Attributes And dbAttachedODBC <> 0 Then
   ' Crée un tableau des éléments de la chaîne de connexion ODBC actuelle
   strParts = Split(td.Connect, ";")
   ' recompose la chaîne de connexion ODBC
   For i = LBound(strParts) To UBound(strParts)
       If strParts(i) Like "UID=*" Then
          ' nouvel attribut UID
          strConn = strConn & "UID=" & strUID & ";"

       ElseIf strParts(i) Like "PWD=*" Then
          ' Nouvel attribut PWD
          strConn = strConn & "PWD=" & strPWD & ";"

       Else
          strConn = strConn & strParts(i) & ";"
       End If
   Next
   strConn = Left(strConn, Len(strConn) - 1)
   ' Modifie la propriété Connect avec la nouvelle chaîne de connexion ODBC
   td.Connect = strConn
   ' Met à jour la liaison
   On Error GoTo ERRH
   td.RefreshLink
   ' RefreshLink recrée la table liée.
   ' ==> on perd l'index unique si on en avait créé un.
   ' Ajout index clé primaire
   If Len(strUniqueRecord) > 0 Then
      strCreateIdx = "CREATE UNIQUE INDEX __uniqueindex " & _
                     "ON  [" & strTable & "] (" & strUniqueRecord & ") WITH PRIMARY"
      db.Execute strCreateIdx, dbFailOnError
   End If

Else
   strErrMsg = "La Table '" & strTable & "' n'est pas une table liée ODBC"
End If

QUIT:
Set td = Nothing
Set db = Nothing
If Len(strErrMsg) <> 0 Then MsgBox strErrMsg
Exit Sub

ERRH:
strErrMsg = "Erreur N° " & CStr(Err.Number) & " : " & Err.Description
Select Case Err.Number
    Case 3146, 3151, 3154, 3155, 3156, 3157, 3231, 3232, 3234, 3225, 3238, 3247, 3254
        strErrMsg = strErrMsg & vbCrLf & vbCrLf & _
           ">>> Erreurs complémentaires DAO :" & vbCrLf & _
           "======================"
        'Récupérations Erreur(s) driver ODBC via DAO
        For Each errX In DBEngine.Errors
            strErrMsg = strErrMsg & vbCrLf & Format(errX.Number, "00000") & " : " & errX.Description
        Next
End Select
Resume QUIT
End Sub

VI. Autres utilisations d'une source donnée ODBC

Les tables liées ne sont pas la seule façon d'exploiter une source ODBC. Elle permet également de faire du SQL direct, ou bien de générer des recordset DAO ou ADO.

VI-A. Requête SQL direct

Une requête "SQL direct" permet d'exécuter une instruction SQL directement depuis le serveur de base de données (SQL Server, MySQL, Oracle, ...).
La syntaxe SQL est celle du SGBD (SQL Server, MySQL, Oracle, ...).

Pour créer une requête SQL Direct, on procède comme pour créer une requête normale, sauf qu'on n'ajoute aucune table.
On ferme la boîte de dialogue "Ajouter une table" et on fait :
Menu principal > Requête > Spécifique SQL > SQL Direct
ou
Clic-droit dans la moitié supérieure de la requête > Spécifique SQL > SQL Direct

Ensuite, on définit la chaîne de connexion ODBC. Elle se trouve dans les propriétés de la requête.
C'est la même que celle utilisée pour lier des tables.

Exemple

 
Sélectionnez
"ODBC;DSN=ESSAI MySQL;UID=Utilisateur;PWD=MotDePasse"

Ce type de requête ne dispose d'aucun moyen de conception visuelle.
On entre juste le texte de l'instruction SQL.
Image non disponible

Les données renvoyées sont en lecture seule.

VI-B. Recordset DAO ODBC

En plus des espaces de travail Microsoft Jet, DAO propose (jusqu'à Access 2003) des espaces de travail ODBC.
Contrairement à Jet, il n'y a pas d'espace de travail par défaut ODBC.
On commence donc par créer un espace de travail ODBC.

  • Dans cet espace de travail ODBC, on ouvre une connexion vers la source de données.
    Là encore il faut une chaîne de connexion ODBC (même syntaxe que celle utilisée pour lier une table ODBC)
  • A partir de la connexion, on ouvre un recordset.

A partir d'Access 2007, les espaces de travail ODBC ne sont plus supportés dans DAO.
Il est cependant possible d'ouvrir une base de données ODBC, depuis l'espace de travail Microsoft Jet par défaut.
Il suffit pour cela, de fournir une chaîne de connexion ODBC à la méthode OpenDatabase.

Comparaison des deux méthodes :

Espace de travail Microsoft Jet Espace de travail ODBC
On peut utiliser l'espace de travail par défaut. On crée un espace de travail ODBC.
Ouvrir une base de données ODBC (DAO.Database) Ouvrir une connexion ODBC (DAO.Connection)
Ouvrir recordset (Database.OpenRecordset) Ouvrir recordset (Connection.OpenRecordset)

Ci-dessous, un exemple de code avec un espace de travail ODBC, et un DSN SQL Serveur :

Exemple recordset DAO ODBC, dans un espace de travail ODBC
Sélectionnez
Sub odbcDAOconn_SqlServer1()
Dim Wksp As DAO.Workspace, Conn As DAO.Connection, strODBCconn As String
Dim rs As DAO.Recordset, strSQL As String, lgIdFournisseur As Long
Dim strUID As String, strPWD As String
Dim errX As DAO.Error, strErrMsg As String

strUID = "Utilisateur"
strPWD = "MotDePasse"

On Error GoTo ERRH

' Créer un nouveau workspace de type ODBC
Set Wksp = DBEngine.CreateWorkspace("MonWkspODBC", "Admin", "", dbUseODBC)
' Chaîne de connexion ODBC
'  - on ne précise pas le nom du serveur (SERVER=NomServeur) car il est
'    déjà enregistré dans la source de données ESSAI SQLSVR (DSN)
'  - on précise le nom de la base de données, 
'    l'utilisateur et le mot de passe
strODBCconn = "ODBC;" & _
              "DSN=ESSAI SQLSVR;" & _
              "DATABASE=EMM;" & _
              "UID=" & strUID & ";PWD=" & strPWD
' Ouverture connexion ODBC
Set Conn = Wksp.OpenConnection("sqlserver", dbDriverNoPrompt, False, strODBCconn)

' Ouverture d'un recordset
strSQL = "SELECT * FROM fournisseurs"
' -  sans l'option dbExecDirect le recordset est en lecture seule
' -  avec MySQL on est toujours en lecture seule (pilote 3.51.23)
Set rs = Conn.Database.OpenRecordset(strSQL, dbOpenDynaset, dbExecDirect, dbPessimistic)
If Not rs.EOF Then
   Debug.Print rs.Fields(0), rs.Fields(1)
End If

' ajoute un enregistrement
If rs.Updatable Then
   rs.AddNew
   rs("Société") = "Nouveau fournisseur"
   rs.Update
   rs.MoveLast
   lgIdFournisseur = rs("N° fournisseur")
   Debug.Print lgIdFournisseur, rs("Société")
End If

QUIT:
If Not rs Is Nothing Then rs.Close
If Not Conn Is Nothing Then Conn.Close
If Not Wksp Is Nothing Then Wksp.Close
Exit Sub

ERRH:

strErrMsg = "Erreur N° " & CStr(Err.Number) & " : " & Err.Description
Select Case Err.Number
    ' principaux codes d'erreurs impliquant ODBC
    Case 3146, 3151, 3154, 3155, 3156, 3157, 3231, 3232, 3234, 3225, 3238, 3247, 3254
        strErrMsg = strErrMsg & vbCrLf & vbCrLf & _
           ">>> Erreurs complémentaires DAO :" & vbCrLf & _
           "======================"
        'Récupérations Erreur(s) driver ODBC via DAO
        For Each errX In DBEngine.Errors
            strErrMsg = strErrMsg & vbCrLf & Format(errX.Number, "00000") & " : " & errX.Description
        Next
End Select

MsgBox strErrMsg
Resume QUIT

End Sub

Le même exemple avec l'espace de travail Microsoft Jet par défaut :

Exemple recordset DAO ODBC, dans un espace de travail Microsoft Jet
Sélectionnez
Sub odbcDAOconn_SqlServer2()
Dim dbodbc As DAO.Database, strODBCconn As String
Dim rs As DAO.Recordset, strSQL As String, lgIdFournisseur As Long
Dim strUID As String, strPWD As String
Dim strErrMsg As String

strUID = "Utilisateur"
strPWD = "MotDePasse"

On Error GoTo ERRH

' Chaîne de connexion ODBC
strODBCconn = "ODBC;" & "DSN=ESSAI SQLSVR;" & "Database=EMM;" & _
              "Uid=" & strUID & ";Pwd=" & strPWD
              
' Ouverture Base ODBC
'   DBEngine(0) équivaut à DBEngine.Workspaces(0)
'   1er argument (dbname) = Nom d'un DSN ou rien
Set dbodbc = DBEngine(0).OpenDatabase("", dbDriverNoPrompt, False, strODBCconn)

' Ouverture d'un recordset
strSQL = "SELECT * FROM fournisseurs"
'
Set rs = dbodbc.OpenRecordset(strSQL, dbOpenDynaset, dbSeeChanges, dbOptimistic)
If Not rs.EOF Then
   Debug.Print rs.Fields(0), rs.Fields(1)
End If

' ajoute un enregistrement
If rs.Updatable Then
   rs.AddNew
   rs("Société") = "Nouveau fournisseur"
   rs.Update
   rs.MoveLast
   lgIdFournisseur = rs("N° fournisseur")
   Debug.Print lgIdFournisseur, rs("Société")
End If

QUIT:
If Not rs Is Nothing Then rs.Close
If Not dbodbc Is Nothing Then dbodbc.Close

Exit Sub

ERRH:
strErrMsg = "Erreur N° " & CStr(Err.Number) & " : " & Err.Description
MsgBox strErrMsg
Resume QUIT

End Sub

VI-C. Recordset ADO

Avec ADO, on dispose généralement d'un fournisseur de données propre à la base de données à laquelle on se connecte.
SQLOLEDB pour SQL Server, MSDAORA pour oracle, Microsoft.Jet.OLEDB.4.0 pour MS-Access, ...

En principe, on utilise le fournisseur de données ODBC (MSDASQL) lorsque l'on n'a pas d'autre choix.
Par exemple c'est ce que l'on fera avec une base de données MySQL si on ne dispose que du pilote ODBC

Exemple recordset ADO ODBC
Sélectionnez
Dim oCnMySQL As ADODB.Connection, rs As ADODB.Recordset

' Connexion à base MySQL
' Crée objet Connection
Set oCnMySQL = New ADODB.Connection
' Définit chaîne de connexion
' * Le provider MSDASQL (ODBC) étant celui par défaut, on peut l'omettre
oCnMySQL.ConnectionString = "Provider=MSDASQL;" & _
                            "DSN=ESSAI MySQL;" & _
                            "UID=Utilisateur;PWD=MotDePasse"
' Ouvre la connexion
oCnMySQL.Open

' Crée recordset
Set rs = New ADODB.Recordset
' Ouvrir recordset sur table fournisseurs
rs.Open "SELECT * FROM fournisseurs", oCnMySQL, adOpenStatic, adLockOptimistic, adCmdText

Debug.Print "AddNew", rs.Supports(adAddNew)
Debug.Print "Update", rs.Supports(adUpdate)
Debug.Print "MovePrevious", rs.Supports(adMovePrevious)
Debug.Print "Find", rs.Supports(adFind)

' Fermeture recordset
rs.Close
Set rs = Nothing
' Fermeture connexion
oCnMySQL.Close
Set oCnMySQL = Nothing

VII. Chaîne de connexion ODBC sans DSN

Il est tout à fait possible d'utiliser des chaînes de connexions ODBC sans DSN (Source de données ODBC).
Dans ce cas la chaîne de connexion doit incorporer le nom du pilote ODBC à utiliser, à l'aide du mot-clé DRIVER.
Par ailleurs, on ne peut plus omettre les éléments SERVER et DATABASE comme on pouvait le faire en utilisant un DSN.

Le format de la chaîne de connexion ODBC ne change pas

 
Sélectionnez
ODBC;mot-clé1=valeur1;mot-clé2=valeur2;...;mot-cléi=valeuri

Rappel : si une valeur à passer en attribut contient un de ces caractères interdits [ ] { } ( ) , ; ? * = ! @ , il faut la mettre entre accolades { }.

Les mots-clés les plus courants :

mots-clés Signification
DRIVER Nom du pilote ODBC
SERVER Nom du serveur
DATABASE Nom de la base de données
UID Nom de l'utilisateur
PWD Mot de passe de l'utilisateur


Voici quelques exemples de chaînes de connexions ODBC :

Chaîne de connexion ODBC pour MySQL
Sélectionnez
ODBC;DRIVER=MySQL ODBC 3.51 Driver;SERVER=LZ2;DATABASE=test;UID=Utilisateur;PWD=MotDePasse;OPTION=3
Chaîne de connexion ODBC pour SQL Server
Sélectionnez
ODBC;DRIVER=SQL Server;SERVER=LZ2;DATABASE=EMM;UID=Utilisateur;PWD=MotDePasse
Chaîne de connexion ODBC pour Oracle
Sélectionnez
ODBC;DRIVER=Microsoft ODBC for Oracle;SERVER=TESTSVR;UID=Utilisateur;PWD=MotDePasse

VIII. Conclusion

J'espère que, grâce à ce tutoriel, vous pourrez tirer profit des liaisons ODBC et qu'il vous aidera à les mettre en application.

Bien qu'ODBC ne soit plus au goût du jour (il y a maintenant OLE DB, ADO), cela reste encore un moyen simple et pratique de se connecter à d'autres systèmes de gestion de base de données.
C'est particulièrement vrai en ce qui concerne les tables liées.

Pensez aux requêtes SQL Direct. Si l'on a besoin uniquement de lire/extraire des données d'un SGBD, les requêtes SQL Direct permettent de faire exécuter les instructions SQL par le serveur de base de données. Cela décharge le client (PC sur lequel Access s'exécute) et le réseau (moindre trafic).
Même remarque concernant les espaces de travail ODBC de DAO.

Pour des connexions purement logicielles (recordsets) j'opterai plutôt pour ADO et un fournisseur de données approprié au SGBD, de manière à bénéficier de plus de fonctionnalités.
Toutefois, pour certains SGBD, ODBC est la seule alternative possible (ou tout du moins la seule gratuite).

Liens

IX. Remerciements

Dolphy35 pour son aide dans mes démarches.
Heureux-oli pour sa relecture.
Antoun pour sa relecture experte, et son aide rédactionnelle.
L'équipe MS-Office de developpez.com pour l'intérêt manifesté à l'égard de mon tuto.
Nono40 pour son outil de création d'article et developpez.com pour leur hébergement.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2008 Christophe Le Fustec. 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.