Rozwijanie aplikacji w C i C++ z użyciem sterownika ODBC

Wersja: 18.7.1.1
Data: 7 września 2026

Aby wywołać API ODBC z C lub C++, należy dołączyć sql.h, sqlext.h, oraz sqltypes.h, a następnie połączyć z biblioteką importu menedżera sterowników. Aby korzystać z rozszerzeń SQL Server, które sterownik Microsoft ODBC dla SQL Server dodaje do standardu ODBC, należy również uwzględnić msodbcsql.h, i dołączyć je po głównych nagłówkach ODBC.

Dotyczy do: Microsoft ODBC Driver 18 dla SQL Server na Windows, Linux i macOS. Wersja 17 używa tej samej nazwy nagłówka z ścieżką 170 instalacji i nazwą biblioteki msodbcsql17 .

Nagłówki i biblioteki

Platforma udostępnia podstawowe pliki nagłówkowe ODBC i menedżer sterowników, a nie pakiet sterowników. W systemie Windows są dostarczane w pakiecie Windows SDK. Na Linuksie i macOS są dostarczane w pakiecie programistycznym unixODBC. Zestaw SDK sterownika udostępnia tylko msodbcsql.h oraz bibliotekę importu zbiorczego.

Tak to nazywasz Nagłówki Windows Linux macOS
ODBC API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
API ODBC, punkty wejścia Unicode Dodaj sqlucode.h odbc32.lib -lodbc -lodbc
Interfejs API instalatora ODBC Dodaj odbcinst.h odbccp32.lib -lodbcinst -lodbcinst
Rozszerzenia sterowników SQL Server Dodaj msodbcsql.h Brak dodatkowej biblioteki Brak dodatkowej biblioteki Brak dodatkowej biblioteki
Funkcje kopiowania masowego (bcp_*) Dodaj msodbcsql.h msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

Nazwa linku kopiowania masowego różni się w zależności od platformy, ponieważ nazwy plików są różne. W systemie Linux -lmsodbcsql-18 jest rozwiązywane przez dowiązanie symboliczne libmsodbcsql-18.so w /usr/lib, które jest już przeszukiwane przez linker, więc nie potrzebujesz -L. W systemie macOS sterownik jest dostarczany jako libmsodbcsql.18.dylib, co odpowiada elementowi -lmsodbcsql.18, ale katalog bibliotek Homebrew nie znajduje się na domyślnej ścieżce wyszukiwania na komputerach Mac z Apple silicon. Dodaj -L$(brew --prefix)/lib podczas łączenia funkcji kopiowania zbiorczego.

Tylko funkcje kopiowania masowego potrzebują własnej biblioteki sterownika. Atrybuty połączenia, atrybuty instrukcji, atrybuty kolumn oraz identyfikatory typów SQL Server to makra i definicje typów, więc wystarczy je uwzględnićmsodbcsql.h.

API instalatora jest odrębną biblioteką od API ODBC. Wywołanie funkcji takiej jak SQLGetPrivateProfileString bez -lodbcinst w systemie Linux lub macOS kończy się na etapie linkowania błędem „undefined reference”, a nie na etapie kompilacji.

Aby zainstalować pakiet deweloperski unixODBC, który zawiera podstawowe pliki nagłówkowe w systemach Linux i macOS, zobacz Install the unixODBC driver manager.

Umieść wchar.h przed msodbcsql.h w kodzie C na Linuksie i macOS

Wersje systemów Linux i macOS składnika msodbcsql.h deklarują interfejs dostawcy magazynu kluczy dla funkcji Always Encrypted przy użyciu wchar_t, ale nie zawierają pliku nagłówkowego definiującego ten typ. W C++ wchar_t jest słowem kluczowym, więc jednostki translacji kompilują się bez potrzeby dołączania dodatkowych plików nagłówkowych. W C element wchar_t jest typedefem, więc najpierw trzeba dołączyć <wchar.h> w jednostce translacji w C:

#include <wchar.h>

Jeśli nie uwzględnisz <wchar.h>, kompilator zgłosi błędy unknown type name 'wchar_t' wewnątrz msodbcsql.h. Dodanie dyrektywy include jest nieszkodliwe w systemie Windows, więc dodaj ją do wspólnego kodu źródłowego, zamiast umieszczać ją za warunkiem platformowym.

Dołącz msodbcsql.h po podstawowych nagłówkach ODBC

Wszystko, co definiuje msodbcsql.h, poza makrami nazwy sterownika, znajduje się wewnątrz bloku #ifdef ODBCVER, a to sql.h definiuje ODBCVER. Jeśli najpierw dołączysz msodbcsql.h, preprocesor pominie cały ten blok, a nagłówek nic nie wniesie. Kompilator nie wydaje żadnego ostrzeżenia.

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

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

Dołączenie msodbcsql.h przed sql.h sprawia, że wszystko wewnątrz bloku ODBCVER jest niezdefiniowane. Kompilator zgłasza błąd w miejscu użycia, a nie przy dyrektywie include:

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

W systemie Windows musisz dołączyć windows.h przed nagłówkami ODBC. Kopie sqltypes.h i sql.h w pakiecie Windows SDK używają typów systemu Windows, takich jak DWORD i LONG. msodbcsql.h umieszcza swoje struktury SQL Server w pshpack8.h i poppack.h. Bez windows.h kompilacja kończy się niepowodzeniem w samych plikach nagłówkowych SDK.

Gdzie zainstalowane są pliki SDK

Platforma msodbcsql.h Biblioteka kopii masowych
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, z symlinkiem /usr/lib/libmsodbcsql-18.so
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

W systemie Windows folder Lib zawiera podfolder dla każdej architektury procesora, którą instalator umieścił na komputerze, na przykład , x64x86, lub arm64. Dodaj folder Include do ścieżki plików dołączanych kompilatora, a podfolder architektury do ścieżki bibliotek linkera.

Na Linuksie współdzielony obiekt jest wersjonowany, nazywany jak libmsodbcsql-18.6.so.2.1, i nie posiada .SONAME Pakiet instaluje /usr/lib/libmsodbcsql-18.so wskazujący na niego, dzięki czemu -lmsodbcsql-18 jest rozpoznawany bez opcji -L. Podłącz się przez ten symlink zamiast nazywać plik wersjonowany, żeby aktualizacja sterownika nie zepsuła twojego builda.

W systemie macOS Homebrew instaluje się we własnym prefiksie, którym jest /opt/homebrew na Apple silicon i /usr/local na Intelu. Oba prefiksy są symlinkami do wersjonowanego katalogu Cellar. Użyj brew --prefix msodbcsql18 i brew --prefix unixodbc w swoim skrypcie buildu zamiast kodować na stałe którykolwiek z nich.

Liczba w ścieżce wskazuje główną wersję sterownika. Wersja 17 jest instalowana w ...\ODBC\170\SDK\ w systemie Windows oraz w /opt/microsoft/msodbcsql17/ w systemie Linux, a jej biblioteką importową jest msodbcsql17.lib.

Pełny wykaz plików dla każdej platformy można znaleźć tutaj: Wymagania systemowe, instalacja i pliki sterownika (Windows), Zainstaluj sterownik ODBC w systemie Linux oraz Zainstaluj sterownik ODBC w systemie macOS.

Sprawdź konfigurację kompilacji

Ten program jest kompilowany z użyciem plików nagłówkowych, linkowany z menedżerem sterowników i wyświetla sterowniki wykrywane przez menedżera sterowników. Nie łączy się, więc oddziela problem z budowaniem lub rejestracją od problemów z siecią lub poświadczeniami.

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

Skompiluj go jako program używający wąskich znaków. SQLODBC_DRIVER_NAME rozwija się do szerokiego łańcucha, gdy zdefiniowano UNICODE lub _UNICODE, którego printf z %s nie może przyjąć.

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

W systemie Windows /W4 zgłasza dwa ostrzeżenia C4201: nonstandard extension used: nameless struct/union z kopii sqlext.h z zestawu Windows SDK. Te ostrzeżenia pochodzą z nagłówka SDK, a nie z twojego kodu, i kompilacja się powiodła.

Pierwsza linia pokazuje nazwę sterownika skompilowaną do twojego pliku binarnego. Cała reszta to własna lista menedżera sterowników, więc jeśli brakuje sterownika, którego oczekujesz, jest to problem z rejestracją, a nie problem z kompilacją. Twoja lista będzie się różnić i zawiera wszystkie zainstalowane sterowniki ODBC, nie tylko te 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)

Zbuduj parametry połączenia na podstawie SQLODBC_DRIVER_NAME, a nie literału ciągu. Makro odwołuje się do pliku nagłówkowego, względem którego skompilowano kod, więc aktualizacja pakietu SDK powoduje zaktualizowanie nazwy sterownika w jednym miejscu.

Co msodbcsql.h dodaje do API ODBC

msodbcsql.h rozszerza standardowy interfejs API ODBC o elementy specyficzne dla programu SQL Server. Każda rodzina zajmuje ciągły zakres liczbowy liczony od stałej bazowej. Zakresy nie są unikalne dla różnych rodzin, więc funkcja, do której przekazujesz wartość, odróżnia je od siebie.

Rodzina Stała bazowa Value
Atrybuty połączeń dla SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Atrybuty zdań dla SQLSetStmtAttr SQL_SOPT_SS_BASE 1225
Atrybuty kolumn dla SQLColAttribute SQL_CA_SS_BASE 1200
Typy informacji dla SQLGetInfo SQL_INFO_SS_FIRST 1199
Pola diagnostyczne dla SQLGetDiagField SQL_DIAG_SS_BASE -1150
Diagnostyczne kody funkcji dynamicznych SQL_DIAG_DFC_SS_BASE -200

Nagłówek deklaruje również:

  • Atrybuty uwierzytelniania, w tym SQL_COPT_SS_AUTHENTICATION i SQL_COPT_SS_ACCESS_TOKEN, które zawierają ustawienia Microsoft Entra ID i tokeny dostępu.
  • Identyfikatory typów SQL w zakresie od -150 do -199 dla typów SQL Server, których ODBC nie definiuje: SQL_SS_VARIANT, SQL_SS_UDT, SQL_SS_XML, SQL_SS_TABLE, SQL_SS_TIME2, SQL_SS_TIMESTAMPOFFSET i SQL_SS_VECTOR. Te nazwy nazywają typ SQL , więc przekazujesz je tam, gdzie ODBC oczekuje typu SQL, na przykład argumentu ParameterTypeSQLBindParameter.
  • Trzy odpowiadające typy C dla strony buforowej: SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, oraz SQL_C_SS_VECTOR. Pozostałe typy SQL Server wiążą się ze standardowym typem ODBC C, takim jak SQL_C_BINARY lub SQL_C_WCHAR, więc nie mają SQL_C_SS_* odpowiednika.
  • Struktury SQL_C_SS_* typu wiążą się z: SQL_SS_TIME2_STRUCT, SQL_SS_TIMESTAMPOFFSET_STRUCT, oraz SQL_SS_VECTOR_STRUCT.
  • Kopiuj prototypy i makra masowo, w tym bcp_init, bcp_bind, bcp_sendrow, bcp_batch, oraz bcp_done. Opcje BCP_ENCRYPT_OFF, BCP_ENCRYPT_ON, i BCP_ENCRYPT_STRICT są dostępne tylko w nagłówku Windows.

Każda platforma wysyła własną kopię msodbcsql.h, i nie wszystkie deklarują te same symbole. Struktura SQLPERF i atrybuty połączenia wydajności, które je wypełniają, takie jak SQL_COPT_SS_PERF_DATA i SQL_COPT_SS_PERF_QUERY, znajdują się tylko w nagłówku Windows. Pliki nagłówkowe systemów Linux i macOS nie deklarują tych elementów, a sterownik nie zbiera danych o wydajności na tych platformach. Zobacz Wytyczne programistyczne (Linux i macOS).

Informacje o słowach kluczowych ciągu połączenia, którym odpowiadają te atrybuty, można znaleźć w temacie DSN oraz słowa kluczowe i atrybuty ciągu połączenia. Aby uzyskać konfigurację Microsoft Entra ID, zobacz Użyj Microsoft Entra ID ze sterownikiem ODBC. Dla typu wektora zobacz Typ danych wektorowy.

Wybierz między wykonywaniem asynchronicznym a wątkami

Niektóre funkcje ODBC mogą działać synchronicznie lub asynchronicznie. W trybie synchronicznym sterownik nie zwraca sterowania, dopóki serwer nie odpowie. W trybie asynchronicznym sterownik natychmiast zwraca kod SQL_STILL_EXECUTING, a aplikacja ponawia to samo wywołanie z tymi samymi argumentami, dopóki nie otrzyma innego kodu zwrotnego. Każdy inny kod zwrotny, w tym SQL_ERROR, oznacza zakończenie operacji.

Tryb asynchroniczny ma dwie formy i używasz jednej z nich. Wywołaj SQLGetInfo z parametrem SQL_ASYNC_MODE, aby sprawdzić, który z nich jest obsługiwany przez sterownik. Zwraca się SQL_AM_STATEMENT , jeśli sterownik obsługuje sterowanie pojedynczą instrukcją, SQL_AM_CONNECTION jeśli ustawienie dotyczy całego połączenia lub SQL_AM_NONE jeśli sterownik w ogóle nie działa asynchronicznie.

Forma instrukcji włącza tryb asynchroniczny dla jednego uchwytu instrukcji. Wszystkie pozostałe instrukcje w ramach połączenia są synchroniczne, więc możesz uruchamiać oba rodzaje jednocześnie:

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

Jeśli SQL_ASYNC_MODE zwraca SQL_AM_CONNECTION, atrybut instrukcji jest atrybutem tylko do odczytu, a to wywołanie zwraca SQL_ERROR z kodem SQLSTATE HYC00. Zamiast tego użyj formularza połączenia.

Ustawienie połączenia włącza tryb asynchroniczny dla wszystkich uchwytów instrukcji, które zostaną później przydzielone w ramach tego połączenia. To, czy wpływa to także na już istniejące uchwyty, zależy od sterownika, więc ustaw to przed przydzieleniem jakichkolwiek poleceń:

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

Wywołanie zwraca SQL_ERROR z kodem SQLSTATE HY010, jeśli funkcja jest nadal wykonywana asynchronicznie dla instrukcji tego połączenia. Sam otwarty kursor nie blokuje połączenia. Przekazanie SQL_ASYNC_ENABLE_OFF przełącza z powrotem wszystkie instrukcje w ramach tego połączenia w tryb synchroniczny.

Aby sprawdzić, ile asynchronicznych instrukcji sterownik obsługuje jednocześnie na jednym połączeniu, wywołaj SQLGetInfo, używając SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Microsoft ODBC Driver 18 dla SQL Server zwraca 1, więc zaplanuj jedną nieoczekiwaną operację asynchroniczną na każde połączenie i otwieraj więcej połączeń lub używaj wątków poza tym limitem. Zobacz Wykonywanie asynchroniczne (metoda odpytywania).

Wątki to inny sposób na równoległe wykonywanie kilku operacji. ODBC wymaga, aby sterowniki w wielowątkowych systemach operacyjnych były bezpieczne w środowisku wielowątkowym, tak aby jeden wątek mógł wykonać blokujące wywołanie funkcji ODBC, podczas gdy inne wątki mogą kontynuować pracę. To unika pętli odpytywania i powtarzających się wywołań funkcji, których potrzebuje tryb asynchroniczny. Nadaj każdemu wątkowi własny uchwyt instrukcji. Sterownik prawdopodobnie będzie wykonywać sekwencyjnie dwa wątki, które jednocześnie używają tego samego uchwytu, więc współdzielenie jednego uchwytu pozbawia Cię współbieżności. Zobacz wielowątkowość. Preferuj wątki w nowym kodzie i zmierz własne obciążenie przed konwersją asynchronicznego kodu, który już działa.

W Windows menedżer sterowników obsługuje również metodę powiadomień, która usuwa pętlę pollingu. Skojarzasz zdarzenie Win32 z uchwytem połączenia lub uchwytem instrukcji. Funkcja nadal zwraca SQL_STILL_EXECUTING natychmiast, a menedżer sterowników sygnalizuje zdarzenie po zakończeniu operacji. W tym trybie odpytywanie jest wyłączone: ponowne wywołanie oryginalnej funkcji zwraca SQL_ERROR z kodem SQLSTATE IM017. Zamiast tego wywołaj SQLCompleteAsync, aby pobrać wynik. Wymaga to wersji menedżera sterowników ODBC 3.81 i nowszych, a sterownik musi to również obsługiwać. Wywołaj SQLGetInfo za pomocą SQL_ASYNC_NOTIFICATION, aby sprawdzić. Zwracana wartość zależy od wersji ODBC zadeklarowanej przez aplikację: w przypadku sterownika Microsoft ODBC Driver 18 for SQL Server aplikacja, która ustawia SQL_ATTR_ODBC_VERSION na SQL_OV_ODBC3_80, otrzymuje SQL_ASYNC_NOTIFICATION_CAPABLE, a aplikacja, która deklaruje SQL_OV_ODBC3, otrzymuje SQL_ASYNC_NOTIFICATION_NOT_CAPABLE z tego samego sterownika. Zadeklaruj SQL_OV_ODBC3_80, zanim przydzielisz połączenie. Zobacz Asynchroniczne wykonanie (metoda powiadomień) oraz próbkę metody powiadomień.

Anuluj niezaległą operację

SQLCancel anuluje operację, która jest nadal wykonywana na uchwycie instrukcji. Dzwon z innego wątku lub z pętli ankietowania, przekazując uchwyt oczekującego połączenia.

Używaj SQLCancel tylko do tego. Aby porzucić zbiór wyników, którego nie chcesz już odczytywać, wywołaj zamiast tego SQLCloseCursor lub SQLMoreResults.

Migrowanie z sqlncli.h do msodbcsql.h

Natywny klient SQL Server został wycofany, więc aplikacje korzystające z niego powinny przejść do sterownika Microsoft ODBC dla SQL Server. Jest to to samo API ODBC, więc większość pracy polega na zmianie nazw parametrów kompilacji i nazwy sterownika w ciągu połączenia.

Klient natywny programu SQL Server Sterownik Microsoft ODBC 18 dla programu 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

Plik nagłówkowy msodbcsql.h nadal definiuje makra nazw SQLNCLI_*, więc kod źródłowy, który ich używa, nadal się kompiluje. Te definicje są chronione przez #ifndef __sqlncli_h__, co oznacza, że nie można uwzględnić obu nagłówków w tej samej jednostce translacyjnej. Usuń dołączenie sqlncli.h.

Dwie rzeczy nie przechodzą dalej:

  • Funkcje API metadanych zapytań rozproszonych, które zwracają listy powiązanych serwerów i ich katalogów, nie są deklarowane w msodbcsql.h. Były one specyficzne dla natywnego klienta SQL Server.
  • Wersja 18 domyślnie szyfruje połączenia i weryfikuje certyfikat serwera. Native Client tego nie zrobił. Parametry połączenia, które działały z klientem Native Client, mogą zakończyć się niepowodzeniem podczas pierwszej próby połączenia, dopóki nie naprawisz problemu z zaufaniem do certyfikatu lub nie ustawisz jawnie elementu Encrypt. Zobacz Rozwiązywanie problemów z szyfrowaniem połączenia.

Na temat pozostałych zmian w wersjach 17 do 18 zobacz Różnice głównych wersji.