Sviluppare applicazioni in C e C++ con il driver ODBC

Versione: 18.7.1.1
Data: 7 settembre 2026

Per chiamare l'API ODBC da C o C++, includere sql.h, sqlext.h, e sqltypes.h, quindi collegarsi alla libreria di importazione del driver manager. Per utilizzare le estensioni di SQL Server che il driver Microsoft ODBC per SQL Server aggiunge allo standard ODBC, includere anche msodbcsql.h e inserirlo dopo gli header ODBC di base.

Vale a: Microsoft ODBC Driver 18 per SQL Server su Windows, Linux e macOS. La versione 17 utilizza lo stesso nome dell’intestazione con un percorso di installazione 170 e un nome della libreria msodbcsql17.

Header e librerie

La piattaforma fornisce le intestazioni ODBC di base e il gestore dei driver, non il pacchetto del driver. Su Windows, vengono forniti nell'SDK di Windows. Su Linux e macOS, vengono inclusi nel pacchetto di sviluppo unixODBC. L'SDK del driver fornisce solo msodbcsql.h e la libreria di importazione bulk copy.

Quello che chiami Intestazioni Windows Linux macOS
ODBC API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
API ODBC, punti di ingresso Unicode Aggiungere sqlucode.h odbc32.lib -lodbc -lodbc
API di installazione ODBC Aggiungere odbcinst.h odbccp32.lib -lodbcinst -lodbcinst
Estensioni del driver SQL Server Aggiungere msodbcsql.h Nessuna biblioteca aggiuntiva Nessuna biblioteca aggiuntiva Nessuna biblioteca aggiuntiva
Funzioni di copia in blocco (bcp_*) Aggiungere msodbcsql.h msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

Il nome del link di copia in blocco varia a seconda della piattaforma perché i nomi dei file differiscono. Su Linux, -lmsodbcsql-18 si risolve tramite un collegamento simbolico libmsodbcsql-18.so in /usr/lib, che il linker cerca già, quindi non è necessario -L. Su macOS, il driver è distribuito come libmsodbcsql.18.dylib, a cui -lmsodbcsql.18 corrisponde, ma la directory delle librerie di Homebrew non rientra nel percorso di ricerca predefinito su Apple Silicon. Aggiungi -L$(brew --prefix)/lib quando colleghi le funzioni di copia in massa.

Solo le funzioni di copia in massa necessitano della libreria del driver. Gli attributi di connessione, attributi di istruzione, attributi di colonna e identificatori di tipo SQL Server sono macro e definizioni di tipo, quindi includere msodbcsql.h è sufficiente per loro.

L'API di installazione è una libreria separata dall'API ODBC. Chiamare una funzione come SQLGetPrivateProfileString without -lodbcinst su Linux o macOS fallisce al tempo del collegamento con un riferimento indefinito, non al momento della compilazione.

Per installare il pacchetto di sviluppo unixODBC che fornisce le intestazioni core su Linux e macOS, consulta Installa il gestore driver unixODBC.

Includere wchar.h prima di msodbcsql.h nel codice C su Linux e macOS

Le versioni per Linux e macOS di msodbcsql.h dichiarano l'interfaccia del provider dell'archivio chiavi Always Encrypted tramite wchar_t, ma non includono un file header che definisca questo tipo. In C++, wchar_t è una parola chiave, quindi le unità di traduzione C++ vengono costruite senza bisogno di header aggiuntivi. In C, wchar_t è una typedef, quindi devi includere <wchar.h> prima in un'unità di traduzione C:

#include <wchar.h>

Se non includi <wchar.h>, il compilatore segnala errori unknown type name 'wchar_t' all'interno di msodbcsql.h. Aggiungere l'include è innocuo su Windows, quindi aggiungilo alla sorgente condivisa invece di metterlo dietro una protezione della piattaforma.

Includere il file msodbcsql.h dopo gli header ODBC principali

Tutto ciò che msodbcsql.h definisce oltre le macro del nome del driver si trova all'interno di un #ifdef ODBCVER blocco, ed sql.h è ciò che definisce ODBCVER. Se includi msodbcsql.h per primo, il preprocessore salta tutto quel blocco e l'intestazione non contribuisce a nulla. Il compilatore non emette alcun avviso.

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

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

L'inclusione di msodbcsql.h prima di sql.h lascia tutto all'interno del blocco ODBCVER non definito. Il compilatore riporta l'errore al punto di utilizzo, non all'include:

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

Su Windows, devi includere windows.h prima delle intestazioni ODBC. Le copie di sqltypes.h e sql.h del Windows SDK utilizzano tipi di Windows come DWORD e LONG. msodbcsql.h racchiude le strutture di SQL Server in pshpack8.h e poppack.h. Senza windows.h, la build fallisce all'interno delle stesse header SDK.

Dove vengono installati i file SDK

Platform msodbcsql.h Libreria di copie in blocco
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, con un /usr/lib/libmsodbcsql-18.so collegamento simmetrico
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

Su Windows, la Lib cartella contiene una sottocartella per ogni architettura processore che l'installer ha inserito sulla macchina, come x64, x86, o arm64. Aggiungi la Include cartella al percorso include del compilatore e la sottocartella architettura al percorso della libreria del linker.

Su Linux, l'oggetto condiviso è versionato, ha un nome del tipo libmsodbcsql-18.6.so.2.1 e non presenta SONAME. Il pacchetto installa /usr/lib/libmsodbcsql-18.so che punta a esso, ed è questo che fa sì che -lmsodbcsql-18 venga risolto senza l'opzione -L. Collegati tramite quel symlink invece di nominare il file versionato, così un aggiornamento del driver non danneggia la tua build.

Su macOS, Homebrew si installa con un prefisso proprio, che è /opt/homebrew su Apple Silicon e /usr/local su Intel. Entrambi i prefissi sono collegamenti simbolici che puntano alla directory Cellar versionata. Usa brew --prefix msodbcsql18 e brew --prefix unixodbc nel tuo script di build invece di codificare in modo rigido uno dei due.

Il numero nel percorso indica la versione principale del driver. La versione 17 si installa su ...\ODBC\170\SDK\ Windows e /opt/microsoft/msodbcsql17/ su Linux, e la sua libreria di importazione è msodbcsql17.lib.

Per l'inventario completo dei file per piattaforma, vedi Requisiti di sistema, installazione e file driver (Windows),Installa il driver ODBC su Linux e Installa il driver ODBC su macOS.

Verifica la configurazione della tua build

Questo programma viene compilato usando gli header, viene collegato al driver manager ed elenca i driver che il driver manager è in grado di vedere. Non si connette, quindi separa un problema di compilazione o registrazione da un problema di rete o credenziali.

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

Costruiscilo come un programma a caratteri ristretti. SQLODBC_DRIVER_NAME si espande in una stringa larga quando UNICODE o _UNICODE è definito, che printf con %s non può prendere.

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

In Windows, /W4 segnala due avvertimenti da parte della copia di sqlext.h inclusa in Windows SDK. Questi avvisi provengono dall'header SDK, non dal tuo codice, e la build ha successo.

La prima riga riporta il nome del driver compilato nel tuo binario. Il resto è l'elenco del gestore dei driver, quindi un driver che ti aspetti di vedere ma non compare è un problema di registrazione, non di compilazione. La tua lista sarà diversa, e include ogni driver ODBC installato, non solo quelli di 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)

Compila la stringa di connessione a partire da SQLODBC_DRIVER_NAME anziché da un valore letterale stringa. La macro tiene traccia del file header con cui hai compilato, quindi l’aggiornamento dell’SDK aggiorna il nome del driver in un solo punto.

Cosa aggiunge msodbcsql.h all'API ODBC

msodbcsql.hestende l'API standard ODBC con specifiche di SQL Server. Ogni famiglia occupa un intervallo numerico contiguo conteggiato da una costante base. Gli intervalli non sono unici tra le famiglie, quindi la funzione a cui passi il valore è ciò che li distingue.

Famiglia Costante base Value
Attributi di connessione per SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Attributi delle istruzioni per SQLSetStmtAttr SQL_SOPT_SS_BASE 1225
Attributi della colonna per SQLColAttribute SQL_CA_SS_BASE 1200
Tipi di informazione per SQLGetInfo SQL_INFO_SS_FIRST 1199
Campi diagnostici per SQLGetDiagField SQL_DIAG_SS_BASE -1150
Codici di funzione dinamica diagnostica SQL_DIAG_DFC_SS_BASE -200

L'intestazione dichiara anche:

  • Attributi di autenticazione, inclusi SQL_COPT_SS_AUTHENTICATION e SQL_COPT_SS_ACCESS_TOKEN, che riportano le impostazioni e i token di accesso di Microsoft Entra ID.
  • Gli identificatori di tipo SQL nell'intervallo compreso tra -150 e -199 per i tipi di SQL Server che ODBC non definisce: SQL_SS_VARIANT, SQL_SS_UDT, SQL_SS_XML, SQL_SS_TABLE, SQL_SS_TIME2, SQL_SS_TIMESTAMPOFFSET e SQL_SS_VECTOR. Questi indicano un tipo SQL, quindi si passano dove ODBC si aspetta un tipo SQL, ad esempio l'argomento ParameterType di SQLBindParameter.
  • Tre tipi C corrispondenti per il lato buffer: SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, e SQL_C_SS_VECTOR. Gli altri tipi di SQL Server sono associati a un tipo ODBC C standard come SQL_C_BINARY o SQL_C_WCHAR, quindi non hanno una controparte SQL_C_SS_*.
  • Le strutture a cui i SQL_C_SS_* tipi si legano: SQL_SS_TIME2_STRUCT, SQL_SS_TIMESTAMPOFFSET_STRUCT, e SQL_SS_VECTOR_STRUCT.
  • Copia in blocco prototipi e macro, inclusi bcp_init, bcp_bind, bcp_sendrow, bcp_batch e bcp_done. Le BCP_ENCRYPT_OFFopzioni , BCP_ENCRYPT_ON, e BCP_ENCRYPT_STRICT sono presenti solo nell'intestazione di Windows.

Ogni piattaforma invia la propria copia di msodbcsql.h, e non tutte dichiarano gli stessi simboli. La SQLPERF struttura e gli attributi di connessione performance che lo riempiono, come SQL_COPT_SS_PERF_DATA e SQL_COPT_SS_PERF_QUERY, sono presenti solo nell'intestazione di Windows. Le header di Linux e macOS non le dichiarano, e il driver non raccoglie dati sulle prestazioni su quelle piattaforme. Vedi le linee guida di programmazione (Linux e macOS).

Per le parole chiave della stringa di connessione a cui corrispondono questi attributi, vedere DSN, parole chiave e attributi della stringa di connessione. Per la configurazione di Microsoft Entra ID, vedi Usa Microsoft Entra ID con il driver ODBC. Per il tipo vettoriale , vedi Tipo di dato vettoriale.

Scegli tra esecuzione asincrona e thread

Alcune funzioni ODBC possono funzionare sia in modo sincrono che asincrono. In modalità sincrona, il driver non restituisce il controllo finché il server non risponde. In modalità asincrona, il driver restituisce SQL_STILL_EXECUTING immediatamente e l'applicazione ripete la stessa chiamata con gli stessi argomenti finché non ottiene un codice di ritorno diverso. Qualsiasi altro codice di ritorno, incluso SQL_ERROR, significa che l'operazione è terminata.

La modalità asincrona ha due forme, e ne usi una. Invoca SQLGetInfo con SQL_ASYNC_MODE per scoprire quale dei due è supportato dal driver. Ritorna SQL_AM_STATEMENT se il driver supporta il controllo per istruzione, SQL_AM_CONNECTION se l'impostazione si applica a tutta la connessione, o SQL_AM_NONE se il driver non esegue affatto funzioni asincronamente.

Il modulo di istruzione attiva la modalità asincrona per un handle dell'istruzione. Ogni altra istruzione sulla connessione rimane sincrona, quindi puoi eseguire entrambi i tipi contemporaneamente:

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

Se SQL_ASYNC_MODE ha restituito SQL_AM_CONNECTION, l'attributo dell'istruzione è di sola lettura e questa chiamata restituisce SQL_ERROR con SQLSTATE HYC00. Usa invece il modulo di connessione.

Il modulo di connessione attiva la modalità asincrona per ogni handle di istruzione che assegni su quella connessione successivamente. Se influenza anche i handle già esistenti è definito dal driver, quindi impostalo prima di assegnare qualsiasi istruzione:

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

La chiamata restituisce SQL_ERROR con SQLSTATE HY010 se una funzione è ancora in esecuzione asincrona per un'istruzione relativa a quella connessione. Un cursore aperto da solo non blocca la chiamata. Il passaggio SQL_ASYNC_ENABLE_OFF riporta ogni istruzione sulla connessione in modalità sincrona.

Per scoprire quante istruzioni asincrone il driver supporta contemporaneamente su una connessione, chiama SQLGetInfo con SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Il driver ODBC 18 di Microsoft per SQL Server restituisce 1, quindi prevedi di avere un'operazione asincrona in sospeso per ogni connessione e, oltre tale limite, apri più connessioni o usa thread. Vedi Esecuzione asincrona (metodo di polling).

I thread sono un altro modo per mantenere attive più operazioni contemporaneamente. ODBC richiede che i driver sui sistemi operativi multithread siano sicuri per thread, così un thread può effettuare una chiamata ODBC bloccante mentre gli altri thread continuano a funzionare. Questo evita il ciclo di polling e le chiamate ripetute di funzioni di cui la modalità asincrona ha bisogno. Assegna a ogni thread il suo handle di affermazione. È probabile che un driver serializzi due thread che usano contemporaneamente lo stesso handle, quindi la condivisione di un handle comporta la perdita della concorrenza. Vedi Multithreading. Preferisci i thread per il nuovo codice e misura il tuo carico di lavoro prima di convertire codice asincrono che già funziona.

In Windows, il gestore dei driver supporta anche il metodo di notifica, che elimina la necessità del ciclo di interrogazione. Associ un evento Win32 al handle della connessione o dell'istruzione. La funzione torna SQL_STILL_EXECUTING comunque immediatamente e il driver manager segnala l'evento quando l'operazione si completa. Il polling è disabilitato in questa modalità: richiamando nuovamente la funzione originale viene restituito SQL_ERROR con SQLSTATE IM017. Chiama SQLCompleteAsync invece per recuperare il risultato. Questo richiede la versione ODBC 3.81 e successive del driver manager, e anche il driver deve supportarla. Chiama SQLGetInfo con SQL_ASYNC_NOTIFICATION per controllare. Il valore che ricevi dipende dalla versione ODBC dichiarata dalla tua applicazione: con Microsoft ODBC Driver 18 per SQL Server, un'applicazione che imposta SQL_ATTR_ODBC_VERSION su SQL_OV_ODBC3_80 gets SQL_ASYNC_NOTIFICATION_CAPABLE, e una che dichiara SQL_OV_ODBC3 gets SQL_ASYNC_NOTIFICATION_NOT_CAPABLE da quello stesso driver. Dichiara SQL_OV_ODBC3_80 prima di assegnare la connessione. Vedi Esecuzione asincrona (metodo notifica) e esempio metodo notifica.

Annullare un'operazione in sospeso

SQLCancel Annulla un'operazione che è ancora in esecuzione su un handle di istruzione. Chiamalo da un altro thread, o dal circuito di sondaggio, passando il controllo della chiamata in sospeso.

Usa SQLCancel solo per quello. Per abbandonare un set di risultati che non vuoi più leggere, chiama invece SQLCloseCursor o SQLMoreResults.

Esegui la migrazione da sqlncli.h a msodbcsql.h

SQL Server Native Client è stato ritirato, quindi le applicazioni che lo utilizzano dovrebbero passare al driver Microsoft ODBC per SQL Server. L'API è la stessa API ODBC, quindi la maggior parte del lavoro consiste nel rinominare gli input di build e il nome del driver nella stringa di connessione.

SQL Server Client Nativo Microsoft ODBC Driver 18+ per 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'intestazione msodbcsql.h definisce ancora le macro SQLNCLI_* per i nomi, quindi il codice sorgente che le utilizza continua a essere compilato. Queste definizioni sono protette da #ifndef __sqlncli_h__, il che significa che non puoi includere entrambi i titoli nella stessa unità di traduzione. Rimuovi l'inclusione sqlncli.h .

Due cose non si trasferiscono:

  • Le funzioni API di metadati di query distribuite che restituiscono liste di server collegati e dei loro cataloghi non sono dichiarate in msodbcsql.h. Erano specifici per SQL Server Native Client.
  • La versione 18 cripta le connessioni di default e valida il certificato server. Native Client non l'ha fatto. Una stringa di connessione che funzionava con Native Client può non riuscire alla prima connessione finché non si corregge l'attendibilità del certificato o non si imposta esplicitamente Encrypt. Vedi Risoluzione dei problemi di crittografia della connessione.

Per il resto delle modifiche dalla versione 17 alla versione 18, vedi Differenze principali nelle versioni.