Développer des applications en C et C++ avec le pilote ODBC

Version : 18.7.1.1
Date : 7 septembre 2026

Pour appeler l’API ODBC depuis C ou C++, incluez sql.h, sqlext.h, et sqltypes.h, puis liez avec la bibliothèque d’importation du gestionnaire de pilotes. Pour utiliser les extensions SQL Server que le pilote Microsoft ODBC pour SQL Server ajoute au-dessus de la norme ODBC, incluez msodbcsql.hégalement , et incluez-la après les en-têtes ODBC de base.

S’applique à : Microsoft ODBC Driver 18 pour SQL Server sur Windows, Linux et macOS. La version 17 utilise le même nom d’en-tête avec un 170 chemin d’installation et un nom de msodbcsql17 bibliothèque.

En-têtes et bibliothèques

La plateforme fournit les en-têtes ODBC de base et le gestionnaire de pilotes, et non le package de pilotes. Sur Windows, ils sont livrés dans le SDK Windows. Sur Linux et macOS, ils sont livrés dans le paquet de développement unixODBC. Le SDK du pilote fournit uniquement msodbcsql.h et la bibliothèque d’importation en bloc.

Ce que tu appelles headers Windows Linux macOS
ODBC API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
API ODBC, points d’entrée Unicode Ajouter sqlucode.h odbc32.lib -lodbc -lodbc
API d’installation ODBC Ajouter odbcinst.h odbccp32.lib -lodbcinst -lodbcinst
Extensions de pilote SQL Server Ajouter msodbcsql.h Pas de bibliothèque supplémentaire Pas de bibliothèque supplémentaire Pas de bibliothèque supplémentaire
Fonctions de copie en masse (bcp_*) Ajouter msodbcsql.h msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

Le nom du lien de copie en bloc diffère selon la plateforme car les noms des fichiers diffèrent. Sous Linux, -lmsodbcsql-18 est résolu via un lien symbolique libmsodbcsql-18.so dans /usr/lib, que l’éditeur de liens recherche déjà, donc vous n’avez pas besoin de -L. Sur macOS, le pilote est livré sous la forme libmsodbcsql.18.dylib, ce à quoi -lmsodbcsql.18 correspond, mais le répertoire des bibliothèques de Homebrew ne figure pas dans le chemin de recherche par défaut sur Apple Silicon. Ajoutez -L$(brew --prefix)/lib lorsque vous liez les fonctions de copie en masse.

Seules les fonctions de copie en masse ont besoin de la propre bibliothèque du pilote. Les attributs connexion, attributs d’instruction, attributs de colonne et identifiants de type SQL Server sont des macros et des définitions de type, donc inclure msodbcsql.h suffit pour eux.

L’API d’installation est une bibliothèque distincte de l’API ODBC. Appeler une fonction comme SQLGetPrivateProfileString sans -lodbcinst sur Linux ou macOS échoue au moment du lien avec une référence non définie, pas au moment de la compilation.

Pour installer le paquet de développement unixODBC qui fournit les en-têtes de base sur Linux et macOS, voir Installer le gestionnaire de pilotes unixODBC.

Inclure wchar.h avant msodbcsql.h dans le code C sous Linux et macOS

Les versions Linux et macOS de msodbcsql.h déclarent l’interface fournisseur de keystore Always Encrypted en utilisant wchar_t, mais elles n’incluent pas d’en-tête définissant ce type. En C++, wchar_t est un mot-clé, donc les unités de traduction C++ se construisent sans avoir besoin d’en-têtes supplémentaires. Dans C, wchar_t est une définition de type, donc vous devez d’abord inclure <wchar.h> dans une unité de traduction C :

#include <wchar.h>

Si vous n’incluez pas <wchar.h>, le compilateur signale des erreurs unknown type name 'wchar_t' dans msodbcsql.h. Ajouter l’inclusion est inoffensif sur Windows, donc ajoutez-le au code source partagé plutôt que de le placer derrière un support de plateforme.

Inclure msodbcsql.h après les en-têtes ODBC de base

Tout ce que msodbcsql.h définit au-delà des macros de noms de pilotes se trouve à l’intérieur d’un bloc #ifdef ODBCVER, et c’est sql.h qui définit ODBCVER. Si vous incluez msodbcsql.h d’abord, le préprocesseur saute tout ce bloc et l’en-tête n’apporte rien. Le compilateur n’émet pas d’avertissement.

/* Correct order. */
#ifdef _WIN32
#include <windows.h>
#endif

#include <wchar.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <msodbcsql.h>

Inclure msodbcsql.h avant la balise sql.h laisse tout ce qui se trouve à l’intérieur du bloc ODBCVER indéfini. Le compilateur rapporte l’erreur au point d’utilisation, et non au point d’inclusion :

order-wrong.c(7): error C2065: 'SQL_COPT_SS_BCP': undeclared identifier

Sur Windows, vous devez inclure windows.h avant les en-têtes ODBC. Les versions du SDK Windows de sqltypes.h et de sql.h utilisent des types Windows tels que DWORD et LONG. msodbcsql.henveloppe ses structures SQL Server dans pshpack8.h et poppack.h. Sans windows.h, la compilation échoue à l’intérieur des en-têtes SDK eux-mêmes.

Où les fichiers SDK sont installés

Platform msodbcsql.h Bibliothèque de copies en vrac
Windows %ProgramFiles%\Microsoft SQL Server\Client SDK\ODBC\180\SDK\Include %ProgramFiles%\Microsoft SQL Server\Client SDK\ODBC\180\SDK\Lib\<architecture>\msodbcsql18.lib
Linux /opt/microsoft/msodbcsql18/include /opt/microsoft/msodbcsql18/lib64, avec un /usr/lib/libmsodbcsql-18.so lien symbolique
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

Sous Windows, le Lib dossier contient un sous-dossier pour chaque architecture processeur placée par l’installateur sur la machine, comme x64, x86, ou arm64. Ajoutez le Include dossier au chemin d’inclusion du compilateur et le sous-dossier architecture au chemin de la bibliothèque du lienneur.

Sous Linux, l’objet partagé est versionné, nommé libmsodbcsql-18.6.so.2.1 et n’a pas d’extension SONAME. Le paquet installe /usr/lib/libmsodbcsql-18.so pointant vers lui, ce qui permet à -lmsodbcsql-18 de se résoudre sans option -L. Faites un lien via ce lien symbolique plutôt que de nommer le fichier versionné, pour qu’une mise à jour du pilote ne casse pas votre build.

Sur macOS, Homebrew s’installe dans son propre préfixe, à savoir /opt/homebrew sur Apple Silicon et /usr/local sur Intel. Les deux préfixes sont des liens symétiques vers le répertoire versionné Cellar. Utilisez brew --prefix msodbcsql18 et brew --prefix unixodbc dans votre script de build au lieu de coder en dur l’un ou l’autre.

Le numéro dans le chemin correspond à la version majeure du pilote. La version 17 s’installe dans ...\ODBC\170\SDK\ sous Windows et dans /opt/microsoft/msodbcsql17/ sous Linux, et sa bibliothèque d’importation est msodbcsql17.lib.

Pour l’inventaire complet des fichiers par plateforme, voir Exigences système, fichiers d’installation et de pilotes (Windows),Installer le pilote ODBC sur Linux, et Installer le pilote ODBC sur macOS.

Vérifie ta configuration de build

Ce programme est compilé avec les fichiers d’en-tête, est lié au gestionnaire de pilotes et répertorie les pilotes que le gestionnaire de pilotes peut détecter. Il ne se connecte pas, donc il sépare un problème de compilation ou d’enregistrement d’un problème réseau ou d’identifiant.

#include <stdio.h>
#include <wchar.h>

#ifdef _WIN32
#include <windows.h>
#endif

#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <msodbcsql.h>

static void PrintDiagnostics(SQLSMALLINT handleType, SQLHANDLE handle)
{
    SQLCHAR state[6];
    SQLINTEGER native;
    SQLCHAR message[SQL_MAX_MESSAGE_LENGTH];
    SQLSMALLINT length;

    for (SQLSMALLINT record = 1;
         SQL_SUCCEEDED(SQLGetDiagRec(handleType, handle, record, state, &native,
                                     message, sizeof(message), &length));
         ++record)
    {
        fprintf(stderr, "  [%s] (%ld) %s\n", state, (long)native, message);
    }
}

int main(void)
{
    SQLHENV environment = SQL_NULL_HENV;
    SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &environment);

    if (!SQL_SUCCEEDED(rc))
    {
        fprintf(stderr, "SQLAllocHandle for the environment failed.\n");
        return 1;
    }

    rc = SQLSetEnvAttr(environment, SQL_ATTR_ODBC_VERSION,
                       (SQLPOINTER)SQL_OV_ODBC3_80, 0);
    if (!SQL_SUCCEEDED(rc))
    {
        fprintf(stderr, "SQLSetEnvAttr for SQL_OV_ODBC3_80 failed.\n");
        PrintDiagnostics(SQL_HANDLE_ENV, environment);
        SQLFreeHandle(SQL_HANDLE_ENV, environment);
        return 1;
    }

    printf("Driver name from msodbcsql.h: %s\n", SQLODBC_DRIVER_NAME);
    printf("Installed drivers:\n");

    SQLCHAR description[256];
    SQLSMALLINT descriptionLength = 0;
    SQLUSMALLINT direction = SQL_FETCH_FIRST;

    while (SQL_SUCCEEDED(SQLDrivers(environment, direction,
                                    description, sizeof(description), &descriptionLength,
                                    NULL, 0, NULL)))
    {
        printf("  %s\n", description);
        direction = SQL_FETCH_NEXT;
    }

    SQLFreeHandle(SQL_HANDLE_ENV, environment);
    return 0;
}

Compilez-le comme un programme en caractères étroits. SQLODBC_DRIVER_NAME se développe en chaîne large lorsque UNICODE ou _UNICODE sont définis, ce que printf avec %s ne peut pas accepter.

cl /W4 /I "%ProgramFiles%\Microsoft SQL Server\Client SDK\ODBC\180\SDK\Include" odbc-build-check.c /link odbc32.lib

Sous Windows, /W4 signale deux avertissements C4201: nonstandard extension used: nameless struct/union provenant de la copie de sqlext.h du SDK Windows. Ces avertissements proviennent de l’en-tête du SDK, pas de votre code, et la compilation réussit.

La première ligne indique le nom du pilote compilé dans votre binaire. Le reste est la propre liste du gestionnaire de pilotes ; ainsi, si un pilote que vous vous attendez à voir n’apparaît pas, il s’agit d’un problème d’enregistrement, pas d’un problème de compilation. Votre liste sera différente, et elle inclut tous les pilotes ODBC installés, pas seulement ceux de SQL Server :

Driver name from msodbcsql.h: ODBC Driver 18 for SQL Server
Installed drivers:
  SQL Server
  ODBC Driver 17 for SQL Server
  ODBC Driver 18 for SQL Server
  Microsoft Access Driver (*.mdb, *.accdb)
  Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
  Microsoft Access Text Driver (*.txt, *.csv)
  Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx)

Générez la chaîne de connexion à partir de SQLODBC_DRIVER_NAME plutôt qu’à partir d’un littéral de chaîne. La macro suit l’en-tête contre lequel vous avez compilé, donc la mise à jour du SDK met à jour le nom du pilote en un seul endroit.

Ce que msodbcsql.h ajoute à l’API ODBC

msodbcsql.hétend l’API standard ODBC avec des spécificités de SQL Server. Chaque famille occupe une plage numérique contiguë comptée à partir d’une constante de base. Les intervalles ne sont pas uniques d’une famille à l’autre, donc c’est la fonction à laquelle vous passez la valeur qui permet de les distinguer.

Famille Constante de base Value
Attributs de connexion pour SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Attributs d’instruction pour SQLSetStmtAttr SQL_SOPT_SS_BASE 1,225
Attributs de colonne pour SQLColAttribute SQL_CA_SS_BASE 1200
Types d’information pour SQLGetInfo SQL_INFO_SS_FIRST 1199
Champs de diagnostic pour SQLGetDiagField SQL_DIAG_SS_BASE -1150
Codes de fonction dynamique de diagnostic SQL_DIAG_DFC_SS_BASE -200

L’en-tête déclare également :

  • Les attributs d’authentification, y compris SQL_COPT_SS_AUTHENTICATION et SQL_COPT_SS_ACCESS_TOKEN, qui portent les paramètres et jetons d’accès de Microsoft Entra ID.
  • Les identifiants de type SQL dans la plage -150 à -199 pour SQL Server types que ODBC ne définit pas : SQL_SS_VARIANT, SQL_SS_UDT, SQL_SS_XML, SQL_SS_TABLE, SQL_SS_TIME2, SQL_SS_TIMESTAMPOFFSET, , et SQL_SS_VECTOR. Celles-ci nomment un type SQL , donc vous les passez là où ODBC attend un type SQL, comme dans l’argument ParameterType de SQLBindParameter.
  • Trois types C correspondants pour le côté tampon : SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, et SQL_C_SS_VECTOR. Les autres types de SQL Server se lient à un type standard ODBC C tel que SQL_C_BINARY ou SQL_C_WCHAR, ils n’ont donc pas SQL_C_SS_* de contreparti.
  • Les structures auxquelles les SQL_C_SS_* types se lient : SQL_SS_TIME2_STRUCT, SQL_SS_TIMESTAMPOFFSET_STRUCT, et SQL_SS_VECTOR_STRUCT.
  • Copier en masse les prototypes et les macros, y compris bcp_init, bcp_bind, bcp_sendrow, bcp_batch et bcp_done. Les BCP_ENCRYPT_OFFoptions , BCP_ENCRYPT_ON, et BCP_ENCRYPT_STRICT se trouvent uniquement dans l’en-tête Windows.

Chaque plateforme expédie sa propre copie de msodbcsql.h, et elles ne déclarent pas toutes les mêmes symboles. La SQLPERF structure et les attributs de connexion performance qui la remplissent, tels que SQL_COPT_SS_PERF_DATA et SQL_COPT_SS_PERF_QUERY, sont uniquement dans l’en-tête Windows. Les en-têtes Linux et macOS ne les déclarent pas, et le pilote ne collecte pas de données de performance sur ces plateformes. Voir les directives de programmation (Linux et macOS).

Pour les mots-clés de chaîne de connexion auxquels ces attributs correspondent, voir DSN et mots-clés et attributs de chaîne de connexion. Pour la configuration de Microsoft Entra ID, voir Utiliser Microsoft Entra ID avec le pilote ODBC. Pour le type de vecteur , voir Type de données vectorielles.

Choisissez entre l’exécution asynchrone et les threads

Certaines fonctions ODBC peuvent s’exécuter de façon synchrone ou asynchrone. En mode synchrone, le pilote ne reprend le contrôle que lorsque le serveur répond. En mode asynchrone, le pilote revient SQL_STILL_EXECUTING immédiatement, et l’application répète le même appel avec les mêmes arguments jusqu’à obtenir un code de retour différent. Tout autre code de retour, y compris SQL_ERROR, signifie que l’opération est terminée.

Le mode asynchrone a deux formes, et vous en utilisez une. Appelez SQLGetInfo avec SQL_ASYNC_MODE pour déterminer lequel est pris en charge par le pilote. Il revient SQL_AM_STATEMENT si le pilote supporte le contrôle par instruction, SQL_AM_CONNECTION si le réglage s’applique à toute la connexion, ou SQL_AM_NONE si le pilote ne fonctionne pas du tout de façon asynchrone.

La forme d’instruction active le mode asynchrone pour un descripteur d’instruction. Toutes les autres instructions sur la connexion restent synchrones, donc vous pouvez exécuter les deux types en même temps :

SQLSetStmtAttr(hStmt, SQL_ATTR_ASYNC_ENABLE,
               (SQLPOINTER)SQL_ASYNC_ENABLE_ON, SQL_IS_INTEGER);

Si SQL_ASYNC_MODE renvoie SQL_AM_CONNECTION, l’attribut d’instruction est en lecture seule et cet appel renvoie SQL_ERROR avec SQLSTATE HYC00. Utilisez plutôt le formulaire de connexion.

Le formulaire de connexion active le mode asynchrone pour chaque handle d’instruction que vous allouez sur cette connexion par la suite. Le fait que cela affecte également les descripteurs déjà existants est défini par le pilote ; définissez-le donc avant d’allouer des instructions SQL :

SQLSetConnectAttr(hDbc, SQL_ATTR_ASYNC_ENABLE,
                  (SQLPOINTER)SQL_ASYNC_ENABLE_ON, SQL_IS_INTEGER);

L’appel renvoie SQL_ERROR avec SQLSTATE HY010 si une fonction s’exécute toujours de manière asynchrone sur une instruction associée à cette connexion. Un curseur ouvert seul ne bloque pas l’appel. Le passage de SQL_ASYNC_ENABLE_OFF fait repasser toutes les instructions de la connexion en mode synchrone.

Pour savoir combien d’instructions asynchrones le pilote supporte simultanément sur une connexion, appelez SQLGetInfo avec SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Le pilote ODBC 18 de Microsoft pour SQL Server renvoie 1 ; tablez donc sur une seule opération asynchrone en attente par connexion et ouvrez davantage de connexions ou utilisez des threads au-delà. Voir Exécution asynchrone (méthode de polling).

Les threads sont une autre façon de garder plusieurs opérations en cours. ODBC impose que les pilotes utilisés dans des systèmes d’exploitation multithread soient thread-safe, de sorte qu’un thread puisse effectuer un appel ODBC bloquant pendant que d’autres threads continuent à s’exécuter. Cela évite la boucle de polling et les appels répétés de fonctions dont le mode asynchrone a besoin. Attribuez à chaque fil son propre handle de phrase. Un pilote est susceptible de sérialiser l’exécution de deux threads qui utilisent le même descripteur en même temps ; en partager un vous fait donc perdre le parallélisme. Voir Multithreading. Privilégiez les threads pour le nouveau code, et mesurez votre propre charge de travail avant de convertir du code asynchrone qui fonctionne déjà.

Sous Windows, le gestionnaire de pilotes prend également en charge la méthode de notification, qui supprime la boucle de polling. Vous associez un événement Win32 au descripteur de connexion ou d’instruction. La fonction renvoie toujours SQL_STILL_EXECUTING immédiatement, et le gestionnaire de pilotes signale l’événement lorsque l’opération est terminée. Le polling est désactivé dans ce mode : appeler à nouveau la fonction originale restitue SQL_ERROR SQLSTATE IM017. Appelle SQLCompleteAsync pour récupérer le résultat à la place. Cela nécessite le gestionnaire de pilotes version ODBC 3.81 et versions ultérieures, et le pilote doit également le supporter. Appelez SQLGetInfo avec SQL_ASYNC_NOTIFICATION pour vérifier. La valeur que vous obtenez en retour dépend de la version d’ODBC que votre application déclare : avec le pilote Microsoft ODBC Driver 18 for SQL Server, une application qui définit SQL_ATTR_ODBC_VERSION sur SQL_ASYNC_NOTIFICATION_CAPABLE obtient SQL_OV_ODBC3_80, tandis qu’une application qui déclare SQL_OV_ODBC3 obtient SQL_ASYNC_NOTIFICATION_NOT_CAPABLE de ce même pilote. Déclarez SQL_OV_ODBC3_80 avant d’attribuer la connexion. Voir Exécution asynchrone (méthode de notification) et l’exemple de méthode de notification.

Annuler une opération en cours

SQLCancel annule une opération toujours en cours d’exécution sur un descripteur d’instruction. Appelez-le depuis un autre fil de discussion, ou depuis la boucle de sondage, en passant le handle de l’appel en attente.

Utilisez-le SQLCancel uniquement pour ça. Pour abandonner un jeu de résultats que vous ne souhaitez plus lire, appelez SQLCloseCursor ou SQLMoreResults à la place.

Migrer de sqlncli.h vers msodbcsql.h

SQL Server Native Client est retiré, donc les applications qui l’utilisent devraient migrer vers le pilote Microsoft ODBC pour SQL Server. L’API est la même API ODBC, donc la majeure partie du travail consiste à renommer les entrées de compilation et le nom du pilote dans la chaîne de connexion.

Client natif SQL Server Microsoft ODBC Driver 18 for SQL Server
sqlncli.h msodbcsql.h
sqlncli11.lib msodbcsql18.lib
sqlncli11.dll msodbcsql18.dll
Driver={SQL Server Native Client 11.0} Driver={ODBC Driver 18 for SQL Server}
SQLNCLI_VER SQLODBC_VER

L’en-tête msodbcsql.h définit toujours les SQLNCLI_* macros de nom, donc le code source qui les utilise continue de compiler. Ces définitions sont protégées par #ifndef __sqlncli_h__, ce qui signifie que vous ne pouvez pas inclure les deux en-têtes dans la même unité de traduction. Retirez l’inclusion sqlncli.h .

Deux choses ne se retrouvent pas :

  • Les fonctions de l’API de métadonnées de requête distribuée qui retournent les listes de serveurs liés et leurs catalogues ne sont pas déclarées dans msodbcsql.h. Ils étaient spécifiques au client natif SQL Server.
  • La version 18 chiffre les connexions par défaut et valide le certificat serveur. Native Client ne l’a pas fait. Une chaîne de connexion qui fonctionnait avec Native Client peut échouer lors de la première connexion tant que vous n’avez pas corrigé le problème de confiance du certificat ou défini explicitement Encrypt. Voir Dépannage du chiffrement de connexion.

Pour le reste des changements de la version 17 à la version 18, voir Différences majeures de version.