Utveckla C- och C++-applikationer med ODBC-drivrutinen

Version: 18.7.1.1
Datum: 7 september 2026

För att anropa ODBC-API:et från C eller C++, inkludera sql.h, sqlext.h, och sqltypes.h, och länka sedan mot drivrutinshanterarens importbibliotek. För att använda de tillägg för SQL Server som Microsoft ODBC-drivrutinen för SQL Server tillför utöver ODBC-standarden, ska du också inkludera msodbcsql.h och inkludera den efter de grundläggande ODBC-huvudfilerna.

Gäller för: Microsoft ODBC Driver 18 för SQL Server på Windows, Linux och macOS. Version 17 använder samma headernamn med en 170 installationssökväg och ett msodbcsql17 biblioteksnamn.

Headerfiler och bibliotek

Plattformen tillhandahåller de centrala ODBC-headers och drivrutinshanteraren, inte drivrutinspaketet. På Windows levereras de i Windows SDK. På Linux och macOS levereras de i utvecklingspaketet unixODBC. Drivrutins-SDK:n tillhandahåller endast msodbcsql.h och bulkkopieringsimportbiblioteket.

Vad du ringer Headers Windows Linux macOS
ODBC API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
ODBC API, Unicode-ingångspunkter Lägg till sqlucode.h odbc32.lib -lodbc -lodbc
ODBC-installations-API Lägg till odbcinst.h odbccp32.lib -lodbcinst -lodbcinst
SQL Server-drivrutinstillägg Lägg till msodbcsql.h Inget extra bibliotek Inget extra bibliotek Inget extra bibliotek
Bulkkopieringsfunktioner (bcp_*) Lägg till msodbcsql.h msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

Namnet på masskopieringslänken skiljer sig mellan plattformar eftersom filnamnen skiljer sig åt. På Linux löses -lmsodbcsql-18 via en libmsodbcsql-18.so-symlänk i /usr/lib, som länkaren redan söker igenom, så du behöver inte -L. På macOS levereras drivrutinen som libmsodbcsql.18.dylib, vilket -lmsodbcsql.18 stämmer, men Homebrews bibliotekskatalog finns inte på standardsökvägen på Apple Silicon. Lägg till -L$(brew --prefix)/lib när du länkar masskopieringsfunktionerna.

Endast funktionerna för masskopiering behöver drivrutinens eget bibliotek. Anslutningsattribut, satsattribut, kolumnattribut och SQL Server-typidentifierare är makron och typdefinitioner, så att inkludera msodbcsql.h räcker för dem.

Installations-API:et är ett separat bibliotek från ODBC-API:et. Att anropa en funktion som SQLGetPrivateProfileString utan -lodbcinst på Linux eller macOS misslyckas vid länkningstid med en odefinierad referens, inte vid kompileringstillfället.

För att installera unixODBC-utvecklingspaketet som tillhandahåller kärnheaders på Linux och macOS, se Installera unixODBC-drivrutinshanteraren.

Inkludera wchar.h före msodbcsql.h i C-kod på Linux och macOS

Linux- och macOS-versionerna av msodbcsql.h deklarerar Always Encrypted keystore-leverantörsgränssnittet genom att använda wchar_t, men de inkluderar inte en header som definierar denna typ. I C++ wchar_t är ett nyckelord, så C++-översättningsenheter byggs utan att behöva extra headers. I C wchar_t är en typdefinition, så du måste först inkludera <wchar.h> i en C-översättningsenhet:

#include <wchar.h>

Om du inte inkluderar <wchar.h>, rapporterar kompilatorn unknown type name 'wchar_t'-fel från insidan av msodbcsql.h. Att lägga till include-satsen är ofarligt i Windows, så lägg till den i den gemensamma källkoden i stället för att placera den bakom ett plattformsvillkor.

Inkludera msodbcsql.h efter de grundläggande ODBC-headerfilerna

Allt som msodbcsql.h definierar bortom drivrutinsnamnsmakron finns inuti ett #ifdef ODBCVER block, och sql.h det är det som definierar ODBCVER. Om du inkluderar msodbcsql.h först hoppar preprocessorn över hela blocket och headern bidrar inte alls. Kompilatorn ger ingen varning.

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

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

Att inkludera msodbcsql.h före sql.h lämnar allt inom blocket ODBCVER odefinierat. Kompilatorn rapporterar felet vid användningstillfället, inte vid inkluderande:

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

På Windows måste du inkludera windows.h före ODBC-headers. Versionerna i Windows SDK av sqltypes.h och sql.h använder Windows-typer såsom DWORD och LONG. msodbcsql.homsluter sina SQL Server-strukturer i pshpack8.h och poppack.h. Utan windows.h misslyckas bygget i själva SDK-huvudfilerna.

Var SDK-filerna installeras

Platform msodbcsql.h Masskopibibliotek
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, med en /usr/lib/libmsodbcsql-18.so symlänk
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

På Windows Lib innehåller mappen en undermapp för varje processorarkitektur som installationsprogrammet placerade på maskinen, såsom x64, x86, eller arm64. Lägg till Include mappen i kompilatorns include-väg och arkitekturundermappen i länkarens biblioteksväg.

På Linux är det delade objektet versionsstyrt, namngivet som libmsodbcsql-18.6.so.2.1, och bär ingen SONAME. Paketet installerar /usr/lib/libmsodbcsql-18.so som pekar på det, vilket gör att -lmsodbcsql-18 kan resolveas utan alternativet -L. Länka via den symlänken istället för att namnge den versionerade filen, så att en drivrutinsuppdatering inte förstör din build.

På macOS har Homebrew ett eget prefix, vilket är /opt/homebrew på Apple silicon och /usr/local på Intel. Båda prefixen är symlänkar till den versionerade Cellar-katalogen. Använd brew --prefix msodbcsql18 och brew --prefix unixodbc i ditt byggskript istället för att hårdkoda något av dem.

Numret i sökvägen anger drivrutinens huvudversion. Version 17 installeras i Windows ...\ODBC\170\SDK\ och i Linux /opt/microsoft/msodbcsql17/, och importbiblioteket är msodbcsql17.lib.

För hela filinventariet per plattform, se Systemkrav, installation och drivrutinsfiler (Windows),Installera ODBC-drivrutinen på Linux och Installera ODBC-drivrutinen på macOS.

Kontrollera din byggkonfiguration

Detta program kompilerar mot headerfilerna, länkar mot drivrutinshanteraren och listar de drivrutiner som drivrutinshanteraren kan se. Den ansluter inte, så den skiljer ett bygg- eller registreringsproblem från ett nätverks- eller inloggningsproblem.

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

Kompilera det som ett program med smala tecken. SQLODBC_DRIVER_NAME expanderar till en bred sträng när UNICODE eller _UNICODE är definierad, vilket printf med %s inte kan ta.

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

På Windows rapporterar /W4 två C4201: nonstandard extension used: nameless struct/union-varningar från Windows SDK:s kopia av sqlext.h. Dessa varningar kommer från SDK-headern, inte från din kod, och bygget lyckas.

Den första raden rapporterar att drivrutinsnamnet kompileras in i din binärfil. Resten är drivrutinshanterarens egen lista, så en drivrutin som du förväntar dig att se men som saknas är ett registreringsproblem, inte ett byggproblem. Din lista kommer att skilja sig, och den inkluderar alla installerade ODBC-drivrutiner, inte bara SQL Server-drivrutinerna:

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)

Bygg anslutningssträngen från SQLODBC_DRIVER_NAME snarare än från en strängliteral. Makrot spårar headern du kompilerade mot, så en uppgradering av SDK:n uppdaterar drivrutinsnamnet på ett ställe.

Vad msodbcsql.h lägger till i ODBC API:et

msodbcsql.hutökar standard-ODBC-API:et med SQL Server-specifika funktioner. Varje familj har ett sammanhängande numeriskt intervall räknat från en baskonstant. Intervallen är inte unika mellan familjer, så funktionen du ger värdet till är det som skiljer dem åt.

Familj Baskonstant Value
Anslutningsattribut för SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Satsattribut för SQLSetStmtAttr SQL_SOPT_SS_BASE 1225
Kolumnattribut för SQLColAttribute SQL_CA_SS_BASE 1200
Informationstyper för SQLGetInfo SQL_INFO_SS_FIRST 1199
Diagnostiska fält för SQLGetDiagField SQL_DIAG_SS_BASE -1150
Diagnostiska dynamiska funktionskoder SQL_DIAG_DFC_SS_BASE -200

Rubriken anger också:

  • Autentiseringsattribut, inklusive SQL_COPT_SS_AUTHENTICATION och SQL_COPT_SS_ACCESS_TOKEN, som bär Microsoft Entra ID-inställningar och åtkomsttoken.
  • SQL-typidentifierare i intervallet -150 till -199 för SQL Server typer som ODBC inte definierar: SQL_SS_VARIANT, , SQL_SS_UDT, SQL_SS_XML, SQL_SS_TABLE, SQL_SS_TIME2, SQL_SS_TIMESTAMPOFFSET, och SQL_SS_VECTOR. Dessa namnger en SQL-typ , så du skickar dem där ODBC förväntar sig en SQL-typ, till exempel argumentet ParameterType i SQLBindParameter.
  • Tre matchande C-typer för buffertsidan: SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, och SQL_C_SS_VECTOR. De andra SQL Server-typerna binder till en standard ODBC C-typ som SQL_C_BINARY eller SQL_C_WCHAR, så de har ingen SQL_C_SS_* motsvarighet.
  • Strukturerna som typerna SQL_C_SS_* binder till: SQL_SS_TIME2_STRUCT, SQL_SS_TIMESTAMPOFFSET_STRUCT, och SQL_SS_VECTOR_STRUCT.
  • Masskopiera prototyper och makron, inklusive bcp_init, , , bcp_sendrowbcp_batch, och bcp_donebcp_bind. , BCP_ENCRYPT_OFFBCP_ENCRYPT_ON, och BCP_ENCRYPT_STRICT alternativen finns endast i Windows-headern.

Varje plattform levererar sin egen kopia av msodbcsql.h, och de deklarerar inte alla samma symboler. Strukturen SQLPERF och prestandaanslutningsattributen som fyller i den, såsom SQL_COPT_SS_PERF_DATA och SQL_COPT_SS_PERF_QUERY, finns endast i Windows-headern. Linux- och macOS-headers deklarerar dem inte, och drivrutinen samlar inte in prestandadata på dessa plattformar. Se Programmeringsriktlinjer (Linux och macOS).

För de reťazec pripojenia-nyckelord som dessa attribut motsvarar, se DSN och reťazec pripojenia-nyckelord och attribut. För Microsoft Entra ID-installation, se Använd Microsoft Entra ID med ODBC-drivrutinen. För vektortypen , se Vektordatatyp.

Välj mellan asynkron exekvering och trådar

Vissa ODBC-funktioner kan köras antingen synkront eller asynkront. I synkront läge återlämnar drivrutinen inte kontrollen förrän servern svarar. I asynkront läge returnerar SQL_STILL_EXECUTING drivrutinen omedelbart, och applikationen upprepar samma anrop med samma argument tills den får en annan returkod. Varje annan returkod, inklusive SQL_ERROR, betyder att operationen är slut.

Asynkront läge har två former, och du använder en av dem. Anropa SQLGetInfo med SQL_ASYNC_MODE för att ta reda på vilken av dem som drivrutinen stöder. Den returnerar SQL_AM_STATEMENT om drivrutinen stödjer kontroll per sats, SQL_AM_CONNECTION om inställningen gäller hela anslutningen, eller SQL_AM_NONE om drivrutinen inte kör funktioner asynkront alls.

Satsformuläret aktiverar asynkront läge för ett satshandtag. Alla andra instruktioner på anslutningen är synkrona, så du kan köra båda typerna samtidigt:

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

Om SQL_ASYNC_MODE returnerar SQL_AM_CONNECTION är instruktionsattributet skrivskyddat och det här anropet returnerar SQL_ERROR med SQLSTATE HYC00. Använd istället kontaktformuläret.

Anslutningsformuläret slår på asynkront läge för varje satshandtag du tilldelar på den anslutningen efteråt. Om det också påverkar handtag som redan finns avgörs av drivrutinen, så ställ in det innan du allokerar några instruktioner:

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

Anropet returnerar SQL_ERROR med SQLSTATE HY010 om en funktion fortfarande körs asynkront på en instruktion för den anslutningen. En öppen markör blockerar inte samtalet i sig. Om du skickar in SQL_ASYNC_ENABLE_OFF återställs alla instruktioner i anslutningen till synkront läge.

För att ta reda på hur många asynkrona satser drivrutinen stöder samtidigt på en anslutning, anropa SQLGetInfo med SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Microsoft ODBC Driver 18 för SQL Server returnerar 1, så planera för en utestående asynkron operation per anslutning och öppna fler anslutningar eller använd trådar utöver det. Se Asynkron körning (pollningsmetoden).

Trådar är det andra sättet att hålla flera operationer igång. ODBC kräver att drivrutiner på multitrådade operativsystem är trådsäkra, så en tråd kan göra ett blockerande ODBC-anrop medan andra trådar fortsätter att arbeta. Det undviker pollingloopen och de upprepade funktionsanrop som asynkront läge behöver. Ge varje tråd ett eget statement-handtag. En drivrutin kommer sannolikt att serialisera två trådar som använder samma handle samtidigt, så om du delar ett går du miste om samtidigheten. Se Multithreading. Föredra trådar för ny kod och mät din egen arbetsbelastning innan du konverterar asynkron kod som redan fungerar.

På Windows stöder drivrutinshanteraren även notifikationsmetoden, vilket tar bort pollingloopen. Du kopplar en Win32-händelse till anslutnings- eller statementhandtaget. Funktionen återvänder SQL_STILL_EXECUTING fortfarande omedelbart, och drivrutinshanteraren signalerar händelsen när operationen slutförs. Polling inaktiveras i detta läge: anrop av den ursprungliga funktionen återvänder SQL_ERROR med SQLSTATE IM017. Ring SQLCompleteAsync för att hämta resultatet istället. Detta kräver drivrutinshanteraren version ODBC 3.81 och senare versioner, och drivrutinen måste också stödja det. Ring SQLGetInfo med SQL_ASYNC_NOTIFICATION för att kontrollera. Värdet du får tillbaka beror på vilken ODBC-version din applikation deklarerar: med Microsoft ODBC Driver 18 för SQL Server, en applikation som sätter SQL_ATTR_ODBC_VERSION till SQL_OV_ODBC3_80 får SQL_ASYNC_NOTIFICATION_CAPABLE, och en som deklarerar SQL_OV_ODBC3 får från SQL_ASYNC_NOTIFICATION_NOT_CAPABLE samma drivrutin. Deklarera SQL_OV_ODBC3_80 innan du tilldelar anslutningen. Se Asynkron exekvering (notifikationsmetod) och provet på notifikationsmetoden.

Avbryt en utestående operation

SQLCancel avbryter en operation som fortfarande körs på ett statementhandtag. Anropa den från en annan tråd eller från pollingloopen och skicka med handtaget för det väntande anropet.

Använd SQLCancel bara för det. Om du vill överge en resultatuppsättning som du inte längre vill läsa, anropar du SQLCloseCursor eller SQLMoreResults i stället.

Migrera från sqlncli.h till msodbcsql.h

SQL Server Native Client är pensionerad, så applikationer som använder den bör flyttas till Microsoft ODBC-drivrutinen för SQL Server. API:et är samma ODBC-API, så det mesta av arbetet handlar om att byta namn på byggindata och drivrutinsnamnet i reťazec pripojenia.

SQL Server Native-klient Microsoft ODBC Driver 18 för 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

Headern för msodbcsql.h definierar fortfarande namnmakrona SQLNCLI_*, så källkod som använder dem kan fortfarande kompileras. Dessa definitioner skyddas av #ifndef __sqlncli_h__, vilket betyder att du inte kan inkludera båda headers i samma översättningsenhet. Ta bort include-satsen sqlncli.h.

Två saker följer inte med:

  • De distribuerade frågemetadata-API-funktionerna som returnerar listor över länkade servrar och deras kataloger deklareras inte i msodbcsql.h. De var specifika för SQL Server Native Client.
  • Version 18 krypterar anslutningar som standard och validerar servercertifikatet. Native Client gjorde det inte. En anslutningssträng som fungerade med Native Client kan misslyckas vid det första anslutningsförsöket tills du åtgärdar tilliten till certifikatet eller anger Encrypt uttryckligen. Se Felsökning av anslutningskryptering.

För resten av ändringarna från version 17 till version 18, se Stora versionsskillnader.