Open DataBase Connectivity
développé par Microsoft est basé sur les spécifications
du SQL Access Group. Il a été d’abord disponible sur Windows et
est maintenant impléménté sur Mac et Unix.
Il permet l’accès
aux données contenues dans des environnements hétérogènes
que ce soient des bases de données relationnelles ou des fichiers (texte,
Excel...) à l’aide:
ODBC utilise un " driver " spécifique à chaque source de données intercalé entre le " driver manager " et les couches spécifiques à l’ensemble de données.C’est ce dernier qui se charge d’appeler le driver spécifique à la source de données avec éventuellement les paramètres adéquats.
Le driver est développé séparément du produit. Initialement par Microsoft puis par les fournisseurs de bases de données ou des spécialistes (Intersolv qui fabrique les drivers Q+E dans le monde Windows, Visigenic dans le monde UNIX ...). Ce qui fait que concrètement on peut avoir plusieurs drivers pour la même source de données avec des caractéristiques et des performance sensiblement différentes.
ODBC se veut donc :
Application ODBC Application native
ODBC Driver Manager (ODBC.DLL)
Oracle Driver (SQORA32.DLL)
SQL*Net Driver
Couches réseau
Serveur
.
ODBC défini deux types de niveau de conformité : API et SQL.Ceux-ci permettent de préjuger si un driver est utilisable pour une application.
API : 3 niveaux de conformité API sont définis : Core , Level 1 et Level 2.(core, niveau minimun de grammaire)
SQL :3 niveaux de conformité SQL sont définis :;Minimum,Core et extended.
Installation des drivers.
Ils doivent faire partie du poste de travail. (Compétence administrateur)
Définition d’une source de données.
Une source de données est un nom défini dans ODBC qui associe une application à un pilote (driver) et à une chaîne de connexion (SGBDR) ou à un repertoire contenant des fichiers (Excel,texte,...).
ex: je peux définir la source de données " mabase " qui sera associé au driver Oracle7 et pointe sur la base " test ",
la source " matable " qui sera associé au driver dBase et pointe sur le répertoire " c:\temp " ... (voir annexe1)
Déclaration :
Il définit les drivers installés.Il est maj quand on installe ou maj un driver.Il ne devrait pas être édité à la main.
[Microsoft Access Driver
(*.mdb) (32 bits)]
Driver=C:\WINNT\System32\odbcjt32.dll
Setup=C:\WINNT\System32\odbcjt32.dll
32Bit=1
[ODBC 32 bit Drivers]
Microsoft Access Driver
(*.mdb) (32 bits)=Installed
Microsoft dBase Driver
(*.dbf) (32 bits)=Installed
Microsoft Excel Driver
(*.xls) (32 bits)=Installed
Microsoft FoxPro Driver
(*.dbf) (32 bits)=Installed
Microsoft Text Driver
(*.txt; *.csv) (32 bits)=Installed
Oracle ODBC Driver
(32 bit)=Installed
[Microsoft dBase Driver
(*.dbf) (32 bits)]
Driver=C:\WINNT\System32\odbcjt32.dll
Setup=C:\WINNT\System32\oddbse32.dll
32Bit=1
[Microsoft Excel Driver
(*.xls) (32 bits)]
Driver=C:\WINNT\System32\odbcjt32.dll
Setup=C:\WINNT\System32\odexl32.dll
32Bit=1
[Microsoft FoxPro
Driver (*.dbf) (32 bits)]
Driver=C:\WINNT\System32\odbcjt32.dll
Setup=C:\WINNT\System32\odfox32.dll
32Bit=1
[Microsoft Text Driver
(*.txt; *.csv) (32 bits)]
Driver=C:\WINNT\System32\odbcjt32.dll
Setup=C:\WINNT\System32\odtext32.dll
32Bit=1
[Oracle ODBC Driver
(32 bit)]
Driver=C:\orant\BIN\SQORA32.DLL
Setup=C:\orant\BIN\SQORAS32.DLL32Bit=1
Fichier ODBC.INI :
Il définit les sources de données. Il est mis à jour par odbcadm ou par l’application elle même (ex ms-query).
Le userid consigné dans ce fichier est proposé par défaut, on peut l’écraser dans la fenêtre qui demande le password.
Les dll mentionnés dans le fichiers doivent évidement exister.
[ODBC 32 bit Data Sources]
MS Access 97 Database=Microsoft Access Driver (*.mdb) (32 bits)
dBASE Files=Microsoft dBase Driver (*.dbf) (32 bits)
Excel Files=Microsoft Excel Driver (*.xls) (32 bits)
FoxPro Files=Microsoft FoxPro Driver (*.dbf) (32 bits)
Text Files=Microsoft Text Driver (*.txt; *.csv) (32 bits)
scott_test=Oracle ODBC Driver (32 bit)
[MS Access 97 Database]
Driver32=C:\WINNT\System32\odbcjt32.dll
[dBASE Files]
Driver32=C:\WINNT\System32\odbcjt32.dll
[Excel Files]
Driver32=C:\WINNT\System32\odbcjt32.dll
[FoxPro Files]
Driver32=C:\WINNT\System32\odbcjt32.dll
[Text Files]
Driver32=C:\WINNT\System32\odbcjt32.dll
[scott_test]
Driver32=D:\Oracle\Ora815\BIN\SQORA32.DLL
ANNEXE 2 : Programmation.
Voici un petit exemple de code ODBC :
D’abord le programme appelant :
/*
* Copyright (c) 1995 – Christian Menaldo
*
* chodbc.c
* FONCTION :
* exemple de programme odbc
*
* MODIFICATIONS :
* Ecrit le 21 mars 1996.
*
*/
#include "windows.h"
#include "SQL.H"
#include <stdio.h>
#include <string.h>
extern void funodbc(UCHAR *server,UCHAR *uid,UCHAR *pwd,UCHAR *sqlstr);
main ()
{
char server[12];
char uid[12];
char pwd[12];
char sqlstr[40];
strcpy(server,"test");
strcpy(uid,"SCOTT");
strcpy(pwd,"TIGER");
strcpy(sqlstr,"select * from emp");
printf ( "Base : %s Compte : %s/%s\nRequête : %s\n",server,uid,pwd,sqlstr);
funodbc (server, uid, NULL,sqlstr) ;
return (0);
}
On se contente ici d’appeler une fonction générique en lui passant la source (test), le compte, le mots de passe et la requête à effectuer.
/*
* Exemple de fonction ODBC
*
* ATTENTION : mettre au link (ou .DEF) le paramètre STACKSIZE à 32000
* sinon erreur Windows memoire
*/
#include "windows.h"
#include "SQL.H"
#include "SQLEXT.H"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAXCOLS 100
/* Calcul de la longueur du libéllé de la colonne */
extern UDWORD caltail(SWORD coltype, UDWORD collen, UCHAR *colname);
/* Deconnexion */
void deconn(HSTMT hstmt,HDBC hdbc,HENV henv);
/* Gestion des esseurs */
void message(HENV henv,HDBC hdbc,HSTMT hstmt);
funodbc (UCHAR *server,UCHAR *uid,UCHAR *pwd,UCHAR *sqlstr)
{
int i;
HENV henv;
HDBC hdbc;
HSTMT hstmt;
UCHAR errmsg[256];
UCHAR colname[32];
SWORD coltype;
SWORD colnamelen;
SWORD nullable;
UDWORD collen[MAXCOLS];
SWORD scale;
UDWORD outlen[MAXCOLS];
UCHAR * data[MAXCOLS];
SWORD nbcols;
SDWORD nbligs;
RETCODE rc;
/* Alloue un handle d'environement.*/
if (SQLAllocEnv(&henv)!= SQL_SUCCESS)
{
printf ("Alloc echouée");
exit (1);
}
/* Alloue un handle de connexion */
if (SQLAllocConnect(henv, &hdbc) != SQL_SUCCESS)
{
printf ("AllocConnect echouée");
exit (1);
}
/* Option de timeout */
SQLSetConnectOption(hdbc, SQL_LOGIN_TIMEOUT, 5);
/* Ici on tente d'établir la connexion (STACKSIZE !!!) */
rc = SQLConnect(hdbc, server, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS) ;
if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf ("Status = %d", rc);
printf ("Connexion refusée\n");
message(henv, hdbc, SQL_NULL_HSTMT);
exit(1);
}
/* Allocation de memoire pour l'ordre SQL */
if (SQLAllocStmt(hdbc, &hstmt) != SQL_SUCCESS)
{
printf ("AllocStmt echouée");
exit (1);
}
/* Execute the SQL statement. */
if (SQLExecDirect(hstmt, sqlstr, SQL_NTS) != SQL_SUCCESS)
{
printf ("Exécution SQL echouée.\n");
deconn(hstmt,hdbc,henv);
exit (1);
}
/* Nombre de lignes uniquement pour maj
if (SQLRowCount(hstmt, &nbligs) != SQL_SUCCESS )
{
printf ("Erreur sur lignes");
deconn(hstmt,hdbc,henv);
exit (1);
}
printf("Nombre de lignes maj : %d" , nbligs);*/
/* Nombre de colonnes récupérées. */
if (SQLNumResultCols(hstmt, &nbcols) > 1)
{
printf ("Trop de colonnes");
deconn(hstmt,hdbc,henv);
exit (1);
}
printf("Nombre de colonnes : %d\n", nbcols);
for (i = 0; i < nbcols; i++)
{
if (SQLDescribeCol(hstmt, i + 1, colname, (SWORD)sizeof(colname),
&colnamelen, &coltype, &collen[i], &scale, &nullable)!= SQL_SUCCESS)
printf("\n Erreur Describe ");
printf("\nType : %d\t nom : %s lg : %d ", coltype , colname,collen[i]);
/*collen[i] = caltail(coltype, collen[i], colname);*/
collen[i] = collen[i] +1;
printf("\tpuis : %d", collen[i]);
data[i] = (UCHAR *) malloc(collen[i]);
if (SQLBindCol(hstmt, i + 1, SQL_C_CHAR, data[i], collen[i],&outlen[i]) != SQL_SUCCESS)
printf("\n Erreur bind ");
}
while (TRUE)
{
rc = SQLFetch(hstmt);
printf("/n");
getchar();
if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
{
errmsg[0] = '\0';
for (i = 0; i < nbcols; i++)
/*if (outlen[i] == SQL_NULL_DATA) strcpy(data[i], "NULL");
else
if (outlen[i] >= collen[i])
{
sprintf(&errmsg[strlen(errmsg)], "%d chars truncated, col %d\n",
outlen - collen + 1,colname);
}
printf("%*.*s ", collen[i], collen[i], data[i]);
printf("\n%s", errmsg); */
{
printf("\t : %s",data[i]);
/*printf("\t==> : %*.*s ", (int) collen[i], (int) collen[i], data[i]);*/
}
}
else
{
printf("\nRC du fetch : %d",rc);
break;
}
}
deconn(hstmt,hdbc,henv);
return 0;
}
void deconn(HSTMT hstmt,HDBC hdbc,HENV henv)
{
SQLFreeStmt(hstmt, SQL_DROP ); /* Free the statement handle. */
SQLDisconnect(hdbc); /* Disconnect from the data source. */
SQLFreeConnect(hdbc); /* Free the connection handle. */
SQLFreeEnv(henv); /* Free the environment handle. */
}
void message(HENV henv,HDBC hdbc,HSTMT hstmt)
{
/* pour les messages retournés par SqlError */
UCHAR FAR *szSqlState; /* SQLSTATE as null terminated string. */
SDWORD FAR *pfNativeError; /* Native error code (specific to the data source).*/
UCHAR FAR *szErrorMsg; /* Pointer to storage for the error message text.*/
SWORD cbErrorMsgMax; /* Maximum length of the szErrorMsg buffer. This must be less than or equal to SQL_MAX_MESSAGE_LENGTH - 1.*/
SWORD FAR *pcbErrorMsg;
cbErrorMsgMax = 50;
if (SQLError(henv, hdbc, hstmt, szSqlState, pfNativeError, szErrorMsg,
cbErrorMsgMax, pcbErrorMsg)!= SQL_SUCCESS)
printf("\n Erreur Erreur... ");
printf("\nErreur ODBC : %s " ,szSqlState);
printf("\nErreur Source : %lf " ,pfNativeError);
printf("\n\t %*s", pcbErrorMsg,szErrorMsg);
}
|