Ontwikkel C- en C++-applicaties met de ODBC-driver

Versie: 18.7.1.1
Datum: 7 september 2026

Om de ODBC API vanuit C of C++ aan te roepen, neemt u sql.h, sqlext.h en sqltypes.h op en koppelt u vervolgens met de importbibliotheek van de driver manager. Om de SQL Server-extensies te gebruiken die de Microsoft ODBC Driver for SQL Server bovenop de ODBC-standaard toevoegt, voeg msodbcsql.hook toe , en voeg deze op na de kernheaders van ODBC.

Van toepassing op: Microsoft ODBC Driver 18 voor SQL Server op Windows, Linux en macOS. Versie 17 gebruikt dezelfde headernaam met een 170 installatiepad en een msodbcsql17 bibliotheeknaam.

Headers en bibliotheken

Het platform levert de kern-ODBC-headers en de driver manager, niet het driverpakket. Op Windows worden ze geleverd met de Windows SDK. Op Linux en macOS worden ze geleverd met het unixODBC-ontwikkelpakket. De driver SDK biedt alleen msodbcsql.h en de bibliotheek voor bulkimport.

Wat je noemt Headers Windows Linux macOS
ODBC-API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
ODBC API, Unicode-toegangspunten sqlucode.h toevoegen odbc32.lib -lodbc -lodbc
ODBC-installatieprogramma-API odbcinst.h toevoegen odbccp32.lib -lodbcinst -lodbcinst
SQL Server-stuurprogramma-extensies msodbcsql.h toevoegen Geen extra bibliotheek Geen extra bibliotheek Geen extra bibliotheek
Functies voor in bulk kopiëren (bcp_*) msodbcsql.h toevoegen msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

De naam van de bulk copy link verschilt per platform omdat de bestandsnamen verschillen. Op Linux wordt -lmsodbcsql-18 opgelost via een libmsodbcsql-18.so symbolische koppeling in /usr/lib, die de linker al doorzoekt, dus heb je -L niet nodig. Op macOS wordt de driver geleverd als libmsodbcsql.18.dylib, wat -lmsodbcsql.18 overeenkomt, maar de bibliotheekmap van Homebrew staat niet op het standaard zoekpad op Apple Silicon. Voeg toe -L$(brew --prefix)/lib wanneer je de bulk-kopieerfuncties linkt.

Alleen de bulk-kopieerfuncties hebben de eigen bibliotheek van het stuurprogramma nodig. Verbindingsattributen, statementattributen, kolomattributen en SQL Server-type-identificaties zijn macro's en typedefinities, dus opnemen msodbcsql.h is voldoende voor hen.

De installer-API is een aparte bibliotheek van de ODBC API. Het aanroepen van een functie zoals SQLGetPrivateProfileString zonder -lodbcinst op Linux of macOS mislukt tijdens het linken met de melding 'undefined reference', niet tijdens het compileren.

Om het unixODBC-ontwikkelpakket te installeren dat de kernheaders op Linux en macOS levert, zie Installeren de unixODBC-drivermanager.

Voeg wchar.h toe vóór msodbcsql.h in C-code op Linux en macOS

De Linux- en macOS-versies van msodbcsql.h declareren de Always Encrypted keystore-providerinterface door wchar_t, maar ze bevatten geen header die dit type definieert. In C++ wchar_t is een trefwoord, dus C++ vertaalunits bouwen zonder extra headers nodig te hebben. In C wchar_t is een typedef, dus je moet eerst opnemen <wchar.h> in een C-translatie-eenheid:

#include <wchar.h>

Als je <wchar.h> niet opneemt, rapporteert de compiler unknown type name 'wchar_t'-fouten in msodbcsql.h. Het toevoegen van de include is onschadelijk op Windows, dus voeg het toe aan de gedeelde bron in plaats van het achter een platformbewaker te plaatsen.

Voeg msodbcsql.h toe na de kernheaders van ODBC

Alles wat msodbcsql.h definieert, afgezien van de drivernaammacro’s, bevindt zich binnen een #ifdef ODBCVER-blok, en sql.h is wat ODBCVER definieert. Als je eerst toevoegt msodbcsql.h , slaat de preprocessor dat hele blok over en draagt de header niets bij. De compiler geeft geen waarschuwing.

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

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

Inclusief msodbcsql.h vóór sql.h laat alles binnen het ODBCVER blok ongedefinieerd. De compiler rapporteert de fout op het moment van gebruik, niet op de include:

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

Op Windows moet je windows.hvóór de ODBC-headers opnemen. De Windows SDK-kopieën van sqltypes.h en sql.h gebruiken Windows-typen zoals DWORD en LONG. msodbcsql.hwikkelt zijn SQL Server-structuren in pshpack8.h en poppack.h. Zonder windows.hfaalt de build binnen de SDK-headers zelf.

Waar de SDK-bestanden zijn geïnstalleerd

Platform msodbcsql.h Massakopiebibliotheek
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, met een /usr/lib/libmsodbcsql-18.so symlink
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

Op Windows bevat de Lib map een submap voor elke processorarchitectuur die de installer op de machine heeft geplaatst, zoals x64, x86, of arm64. Voeg de map Include toe aan het include-zoekpad van de compiler en de architectuursubmap aan het bibliotheekzoekpad van de linker.

Op Linux is het gedeelde object versiegebonden, benoemd als libmsodbcsql-18.6.so.2.1, en draagt geen .SONAME Het pakket installeert /usr/lib/libmsodbcsql-18.so die ernaar verwijst, waardoor -L wordt opgelost zonder een -lmsodbcsql-18-optie. Link via die symlink in plaats van het versiebestand te benoemen, zodat een driverupdate je build niet kapot maakt.

Op macOS installeert Homebrew in zijn eigen prefix, namelijk /usr/local op Apple silicon en /opt/homebrew op Intel. Beide prefixen zijn symlinks naar de geversioneerde Cellar-map. Gebruik brew --prefix msodbcsql18 en brew --prefix unixodbc in je build-script in plaats van een van beide hardcoderen.

Het nummer in het pad geeft de versie van de hoofdbestuurder weer. Versie 17 wordt onder Windows geïnstalleerd in ...\ODBC\170\SDK\ en onder Linux in /opt/microsoft/msodbcsql17/, en de importbibliotheek is msodbcsql17.lib.

Voor de volledige bestandsinventaris per platform, zie Systeemvereisten, installatie en driverbestanden (Windows),Installeer de ODBC-driver op Linux, en Installeer de ODBC-driver op macOS.

Controleer je build-setup

Dit programma compileert met de headers, koppelt naar de driver manager en geeft een lijst van de drivers die de driver manager kan zien. Het maakt geen verbinding, dus het scheidt een build- of registratieprobleem van een netwerk- of credentialprobleem.

#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;
}

Bouw het als een programma met smalle tekens. SQLODBC_DRIVER_NAME zet uit tot een brede string wanneer UNICODE of _UNICODE gedefinieerd is, wat printf met %s niet kan nemen.

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

Op Windows meldt /W4 twee C4201: nonstandard extension used: nameless struct/union-waarschuwingen van de Windows SDK-kopie van sqlext.h. Deze waarschuwingen komen van de SDK-header, niet van je code, en de build slaagt.

De eerste regel vermeldt de stuurprogrammanaam die in je binary is gecompileerd. De rest komt uit de eigen lijst van het stuurprogrammabeheer, dus als een stuurprogramma dat je verwacht te zien ontbreekt, is dat een probleem met de registratie, niet met de build. Je lijst zal verschillen, en die bevat elke geïnstalleerde ODBC-driver, niet alleen die van 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)

Bouw de verbindingsreeks op vanuit SQLODBC_DRIVER_NAME in plaats van vanuit een letterlijke tekenreeks. De macro volgt de header waarvoor je hebt gecompileerd, dus het upgraden van de SDK werkt de drivernaam op één plek bij.

Wat msodbcsql.h toevoegt aan de ODBC API

msodbcsql.hbreidt de standaard ODBC API uit met SQL Server-specificaties. Elke familie bezet een aaneengesloten numeriek bereik dat wordt geteld vanaf een basisconstante. De bereiken zijn niet uniek tussen families, dus de functie waaraan je de waarde doorgeeft, is wat ze uit elkaar houdt.

Familie Basisconstante Value
Verbindingsattributen voor SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Statement-attributen voor SQLSetStmtAttr SQL_SOPT_SS_BASE 1225
Kolomattributen voor SQLColAttribute SQL_CA_SS_BASE 1200
Informatietypen voor SQLGetInfo SQL_INFO_SS_FIRST 1199
Diagnostische velden voor SQLGetDiagField SQL_DIAG_SS_BASE -1150
Diagnostische dynamische functiecodes SQL_DIAG_DFC_SS_BASE -200

De kop verklaart ook:

  • Authenticatieattributen, waaronder SQL_COPT_SS_AUTHENTICATION en SQL_COPT_SS_ACCESS_TOKEN, die Microsoft Entra ID-instellingen en toegangstokens bevatten.
  • SQL-type-identificaties in het bereik -150 tot -199 voor SQL Server types die ODBC niet definieert: SQL_SS_VARIANT, , SQL_SS_UDT, SQL_SS_XML, SQL_SS_TABLE, SQL_SS_TIME2, SQL_SS_TIMESTAMPOFFSET, en SQL_SS_VECTOR. Deze benoemen een SQL-type , dus je geeft ze waar ODBC een SQL-type verwacht, zoals het ParameterType argument van SQLBindParameter.
  • Drie overeenkomende C-typen voor de bufferzijde: SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, en SQL_C_SS_VECTOR. De andere SQL Server-types binden aan een standaard ODBC C-type zoals SQL_C_BINARY of SQL_C_WCHAR, dus ze hebben geen SQL_C_SS_* tegenhanger.
  • De structuren waaraan de SQL_C_SS_* typen zich binden: SQL_SS_TIME2_STRUCT, , SQL_SS_TIMESTAMPOFFSET_STRUCTen SQL_SS_VECTOR_STRUCT.
  • Kopieer meerdere prototypes en macro’s tegelijk, inclusief bcp_init, bcp_bind, bcp_sendrow, bcp_batch en bcp_done. De BCP_ENCRYPT_OFF, BCP_ENCRYPT_ON, en BCP_ENCRYPT_STRICT opties staan alleen in de Windows-header.

Elk platform levert zijn eigen kopie van msodbcsql.h, en ze geven niet allemaal dezelfde symbolen aan. De SQLPERF structuur en de prestatie-verbindingsattributen die deze invullen, zoals SQL_COPT_SS_PERF_DATA en SQL_COPT_SS_PERF_QUERY, staan alleen in de Windows-header. De Linux- en macOS-headers declareren ze niet, en de driver verzamelt geen prestatiegegevens op die platforms. Zie Programmeerrichtlijnen (Linux en macOS).

Voor de verbindingsreeks-sleutelwoorden waaraan deze attributen behoren, zie DSN en verbindingsreeks keywords and attributs. Voor Microsoft Entra ID-setup, zie Gebruik Microsoft Entra ID met de ODBC-driver. Voor het vectortype , zie Vector data type.

Kies tussen asynchrone uitvoering en threads

Sommige ODBC-functies kunnen zowel synchroon als asynchroon draaien. In synchrone modus geeft de driver de controle pas terug als de server antwoordt. In asynchrone modus keert de driver direct terug SQL_STILL_EXECUTING , en herhaalt de applicatie dezelfde aanroep met dezelfde argumenten totdat het een andere retourcode krijgt. Elke andere retourcode, inclusief SQL_ERROR, betekent dat de bewerking is voltooid.

Asynchrone modus heeft twee vormen, en je gebruikt er één van. Roep SQLGetInfo aan met SQL_ASYNC_MODE om te achterhalen welke door het stuurprogramma wordt ondersteund. Het geeft terug SQL_AM_STATEMENT als de driver per-instructie controle ondersteunt, SQL_AM_CONNECTION als de instelling op de hele verbinding van toepassing is, of SQL_AM_NONE als de driver helemaal geen asynchroon functies uitvoert.

De statementvorm schakelt de asynchrone modus in voor één statement-handle. Elke andere instructie op de verbinding blijft synchroon, dus je kunt beide soorten tegelijk uitvoeren:

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

Als SQL_ASYNC_MODESQL_AM_CONNECTION retourneert, is het instructiekenmerk alleen-lezen en retourneert deze aanroep SQL_ERROR met SQLSTATE HYC00. Gebruik in plaats daarvan het verbindingsformulier.

Het verbindingsformulier zet de asynchrone modus aan voor elke instructiehandle die je daarna op die verbinding toewijst. Of dit ook van invloed is op handles die al bestaan, wordt door de driver bepaald, dus stel dit in voordat je statements alloceert:

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

De aanroep keert terug SQL_ERROR met SQLSTATE HY010 als een functie nog steeds asynchroon uitvoert op een instructie voor die verbinding. Een open cursor op zichzelf blokkeert de oproep niet. Het doorgeven van SQL_ASYNC_ENABLE_OFF zet alle instructies op de verbinding weer in de synchrone modus.

Om te bepalen hoeveel asynchrone statements de driver tegelijk ondersteunt via één verbinding, roep je SQLGetInfo aan met SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Microsoft ODBC Driver 18 voor SQL Server geeft 1 terug, dus reken op één openstaande asynchrone bewerking per verbinding en open meer verbindingen of gebruik threads daarboven. Zie Asynchrone uitvoering (pollingmethode).

Threads zijn een andere manier om meerdere bewerkingen gelijktijdig uit te voeren. ODBC vereist dat drivers op multithreaded besturingssystemen threadveilig zijn, zodat een thread een blokkerende ODBC-aanroep kan maken terwijl andere threads blijven werken. Dat voorkomt de polling-lus en de herhaalde functieaanroepen die de asynchrone modus nodig heeft. Geef elke thread een eigen statement-handle. Een driver zal waarschijnlijk twee threads serialiseren die tegelijkertijd hetzelfde handle gebruiken, dus het delen van één draad kost je de gelijktijdigheid. Zie Multithreading. Geef de voorkeur aan threads voor nieuwe code, en meet je eigen workload voordat je asynchrone code converteert die al werkt.

Op Windows ondersteunt de drivermanager ook de notificatie-methode, waarmee de polling-lus wordt verwijderd. Je koppelt een Win32-event aan de verbindingshandle of instructiehandle. De functie keert nog steeds direct terug SQL_STILL_EXECUTING , en de driver manager geeft het signaal aan wanneer de bewerking is voltooid. Polling is in deze modus uitgeschakeld: het opnieuw aanroepen van de oorspronkelijke functie geeft SQL_ERROR terug met SQLSTATE IM017. Roep SQLCompleteAsync aan om in plaats daarvan het resultaat op te halen. Dit vereist drivermanagerversie ODBC 3.81 en latere versies, en de driver moet dit ook ondersteunen. Bel SQLGetInfo om het met SQL_ASYNC_NOTIFICATION te controleren. De waarde die je terugkrijgt hangt af van de ODBC-versie die je applicatie aangeeft: met Microsoft ODBC Driver 18 voor SQL Server, een applicatie die zet SQL_ATTR_ODBC_VERSION op SQL_OV_ODBC3_80 gets SQL_ASYNC_NOTIFICATION_CAPABLE, en een die declareert SQL_OV_ODBC3 gets SQL_ASYNC_NOTIFICATION_NOT_CAPABLE van diezelfde driver. Declareer SQL_OV_ODBC3_80 voordat je de verbinding toewijst. Zie Asynchrone uitvoering (notificatiemethode) en het voorbeeld van de notificatiemethode.

Annuleer een openstaande operatie

SQLCancel annuleert een bewerking die nog wordt uitgevoerd op een statement-handle. Roep deze aan vanuit een andere thread, of vanuit de polling-lus, en geef daarbij de handle van de openstaande aanroep door.

Gebruik SQLCancel alleen daarvoor. Om een resultaatset die je niet langer wilt lezen los te laten, roep je in plaats daarvan SQLCloseCursor of SQLMoreResults aan.

Migreren van sqlncli.h naar msodbcsql.h

SQL Server Native Client is buiten gebruik gesteld, dus applicaties die het gebruiken zouden moeten overstappen naar de Microsoft ODBC-driver voor SQL Server. De API is dezelfde ODBC API, dus het meeste werk bestaat uit het hernoemen van build-invoer en de drivernaam in de verbindingsreeks.

SQL Server Native Client Microsoft ODBC-stuurprogramma 18 voor 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

De msodbcsql.h header definieert nog steeds de SQLNCLI_* naam-macro's, dus de broncode die ze gebruikt blijft compileren. Deze definities worden beschermd door #ifndef __sqlncli_h__, wat betekent dat je niet beide headers in dezelfde vertaaleenheid kunt opnemen. Verwijder de toevoeging sqlncli.h .

Twee dingen worden niet meegenomen:

  • De gedistribueerde query metadata API werkt als een functie die lijsten van gekoppelde servers terugstuurt en hun catalogi worden niet gedeclareerd in msodbcsql.h. Ze waren specifiek voor SQL Server Native Client.
  • Versie 18 versleutelt de verbindingen standaard en valideert het servercertificaat. Native Client deed dat niet. Een verbindingsreeks die werkte met Native Client kan falen bij de eerste verbinding totdat je certificaatvertrouwen corrigeert of expliciet insteltEncrypt. Zie Problemen met verbindingsversleuteling oplossen.

Voor de rest van de wijzigingen van versie 17 naar versie 18, zie Belangrijke versieverschillen.