Kembangkan aplikasi C dan C++ dengan driver ODBC

Versi: 18.7.1.1
Tanggal: 7 September 2026

Untuk memanggil API ODBC dari C atau C++, sertakan sql.h, sqlext.h, dan sqltypes.h, lalu tautkan ke pustaka impor driver manager. Untuk menggunakan ekstensi SQL Server yang ditambahkan Microsoft ODBC Driver for SQL Server sebagai pelengkap standar ODBC, sertakan juga msodbcsql.h, dan sertakan setelah header ODBC inti.

Berlaku untuk: Microsoft ODBC Driver 18 untuk SQL Server di Windows, Linux, dan macOS. Versi 17 menggunakan nama header yang sama dengan jalur instalasi 170 dan nama pustaka msodbcsql17.

Header dan pustaka

Platform menyediakan header inti ODBC dan driver manager, bukan paket driver. Pada Windows, komponen tersebut disertakan dalam Windows SDK. Di Linux dan macOS, mereka disertakan dalam paket pengembangan unixODBC. SDK driver hanya menyediakan msodbcsql.h dan pustaka impor salin massal.

Apa yang kamu sebut Headers Windows Linux macOS
ODBC API sql.h, sqlext.h, sqltypes.h odbc32.lib -lodbc -lodbc
API ODBC, titik masuk Unicode Tambahkan sqlucode.h odbc32.lib -lodbc -lodbc
API penginstal ODBC Tambahkan odbcinst.h odbccp32.lib -lodbcinst -lodbcinst
Ekstensi driver SQL Server Tambahkan msodbcsql.h Tidak ada perpustakaan tambahan Tidak ada perpustakaan tambahan Tidak ada perpustakaan tambahan
Fungsi salinan massal (bcp_*) Tambahkan msodbcsql.h msodbcsql18.lib -lmsodbcsql-18 -lmsodbcsql.18

Nama tautan salinan massal berbeda menurut platform karena nama file berbeda. Di Linux, -lmsodbcsql-18 terselesaikan melalui libmsodbcsql-18.so symlink di /usr/lib, yang sudah dicari oleh linker, jadi Anda tidak perlu -L. Di macOS, driver dikirim sebagai libmsodbcsql.18.dylib, yang -lmsodbcsql.18 cocok, tetapi direktori perpustakaan Homebrew tidak ada di jalur pencarian default di Apple silicon. Tambahkan -L$(brew --prefix)/lib saat Anda menghubungkan fungsi salinan massal.

Hanya fungsi penyalinan massal yang memerlukan pustaka milik driver itu sendiri. Atribut koneksi, atribut pernyataan, atribut kolom, dan pengenal tipe SQL Server adalah makro dan definisi tipe, jadi menyertakan msodbcsql.h sudah cukup untuk mereka.

API installer adalah pustaka terpisah dari API ODBC. Memanggil fungsi seperti SQLGetPrivateProfileString tanpa -lodbcinst di Linux atau macOS gagal pada tahap penautan dengan galat referensi tak terdefinisi, bukan pada tahap kompilasi.

Untuk menginstal paket pengembangan unixODBC yang menyediakan header inti di Linux dan macOS, lihat Instal driver manager unixODBC.

Sertakan wchar.h sebelum msodbcsql.h dalam kode C di Linux dan macOS

Versi Linux dan macOS dari msodbcsql.h mendeklarasikan antarmuka penyedia keystore Always Encrypted melalui wchar_t, tetapi tidak menyertakan header yang mendefinisikan tipe ini. Dalam C++, wchar_t adalah kata kunci, sehingga unit terjemahan C++ dibangun tanpa perlu header tambahan. Dalam C, wchar_t adalah typedef, jadi Anda perlu memasukkan <wchar.h> terlebih dahulu dalam unit terjemahan C:

#include <wchar.h>

Jika Anda tidak menyertakan <wchar.h>, kompilator melaporkan kesalahan unknown type name 'wchar_t' dari dalam msodbcsql.h. Menambahkan include tidak berbahaya di Windows, jadi tambahkan ke sumber bersama daripada menempatkannya di belakang platform guard.

Sertakan msodbcsql.h setelah header utama ODBC

Segala sesuatu yang msodbcsql.h mendefinisikan di luar makro nama driver berada di dalam #ifdef ODBCVER sebuah blok, dan sql.h itulah yang mendefinisikan ODBCVER. Jika Anda memasukkan msodbcsql.h terlebih dahulu, preprocessor melewati seluruh blok itu dan header tidak memberikan kontribusi apa-apa. Kompiler tidak mengeluarkan peringatan.

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

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

Menyertakan msodbcsql.h sebelum sql.h membuat semua yang ada di dalam ODBCVER blok tidak terdefinisi. Kompilator melaporkan kesalahan pada titik penggunaan, bukan pada termasuk:

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

Di Windows, Anda harus menyertakan windows.h sebelum header ODBC. Salinan sqltypes.h dan sql.h dari Windows SDK menggunakan tipe Windows seperti DWORD dan LONG. msodbcsql.hmembungkus struktur SQL Server-nya dalam pshpack8.h dan poppack.h. Tanpa windows.h, build gagal di dalam header SDK itu sendiri.

Tempat file SDK diinstal

Platform msodbcsql.h Perpustakaan salinan massal
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, dengan /usr/lib/libmsodbcsql-18.so tautan simbolis
macOS $(brew --prefix msodbcsql18)/include/msodbcsql18 $(brew --prefix)/lib/libmsodbcsql.18.dylib

Di Windows, folder tersebut Lib berisi subfolder untuk setiap arsitektur prosesor yang dipasang installer di mesin, seperti x64, x86, atau arm64. Tambahkan folder Include ke jalur penyertaan kompiler dan subfolder arsitektur ke jalur pustaka linker.

Pada Linux, shared object memiliki versi, diberi nama seperti libmsodbcsql-18.6.so.2.1, dan tidak memiliki SONAME. Paket menginstal /usr/lib/libmsodbcsql-18.so yang mengarah ke sana, yang memungkinkan -lmsodbcsql-18 diresolusikan tanpa opsi -L. Tautkan melalui symlink itu daripada menamai file versi tersebut, agar pembaruan driver tidak merusak build Anda.

Di macOS, Homebrew diinstal ke prefiksnya sendiri, yaitu /opt/homebrew pada Apple silicon dan /usr/local pada Intel. Kedua prefiks tersebut adalah symlink yang mengarah ke direktori Cellar berversi. Gunakan brew --prefix msodbcsql18 dan brew --prefix unixodbc di skrip build Anda daripada melakukan hardcoding salah satunya.

Nomor di jalur melacak versi pengemudi utama. Versi 17 diinstal ke ...\ODBC\170\SDK\ pada Windows dan /opt/microsoft/msodbcsql17/ pada Linux, dan pustaka impornya adalah msodbcsql17.lib.

Untuk inventaris file lengkap per platform, lihat Persyaratan sistem, instalasi, dan file driver (Windows),Instal driver ODBC di Linux, dan Instal driver ODBC di macOS.

Verifikasi pengaturan build Anda

Program ini dikompilasi menggunakan header, ditautkan dengan manajer driver, dan menampilkan daftar driver yang dapat dikenali oleh manajer driver. Tidak tersambung, sehingga dapat membedakan masalah build atau registrasi dari masalah jaringan atau kredensial.

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

Buat sebagai program karakter sempit. SQLODBC_DRIVER_NAME diperluas menjadi string karakter lebar saat UNICODE atau _UNICODE didefinisikan, yang tidak dapat diterima oleh printf dengan %s.

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

Pada Windows, /W4 melaporkan dua peringatan C4201: nonstandard extension used: nameless struct/union dari salinan sqlext.h yang ada di Windows SDK. Peringatan ini berasal dari header SDK, bukan dari kode Anda, dan build berhasil.

Baris pertama menampilkan nama driver yang dikompilasi ke biner Anda. Sisanya adalah daftar milik pengelola driver itu sendiri, jadi jika ada driver yang Anda harapkan muncul tetapi tidak ada, itu adalah masalah registrasi, bukan masalah build. Daftar Anda akan berbeda, dan mencakup semua driver ODBC yang terpasang, bukan hanya yang 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)

Buat string koneksi dari SQLODBC_DRIVER_NAME, bukan dari literal string. Makro ini mengacu pada header yang Anda gunakan saat kompilasi, sehingga saat SDK dimutakhirkan, nama driver diperbarui di satu tempat.

Apa yang ditambahkan msodbcsql.h ke API ODBC

msodbcsql.hmemperluas API ODBC standar dengan spesifikasi SQL Server. Setiap keluarga menempati rentang numerik yang berturut-turut yang dihitung dari konstanta dasar. Rentang tersebut tidak unik di setiap keluarga, jadi fungsi yang Anda berikan nilai itulah yang membedakannya.

Keluarga Konstanta basis Value
Atribut koneksi untuk SQLSetConnectAttr SQL_COPT_SS_BASE 1200
Atribut pernyataan untuk SQLSetStmtAttr SQL_SOPT_SS_BASE 1225
Atribut kolom untuk SQLColAttribute SQL_CA_SS_BASE 1200
Jenis informasi untuk SQLGetInfo SQL_INFO_SS_FIRST 1199
Bidang diagnosis untuk SQLGetDiagField SQL_DIAG_SS_BASE -1150
Kode fungsi dinamis diagnostik SQL_DIAG_DFC_SS_BASE -200

Header juga menyatakan:

  • Atribut autentikasi, termasuk SQL_COPT_SS_AUTHENTICATION dan SQL_COPT_SS_ACCESS_TOKEN, yang membawa pengaturan Microsoft Entra ID dan token akses.
  • Pengidentifikasi tipe SQL dalam rentang -150 menjadi -199 untuk tipe SQL Server yang tidak didefinisikan oleh ODBC: SQL_SS_VARIANT, , SQL_SS_UDT, SQL_SS_TIME2SQL_SS_TIMESTAMPOFFSETSQL_SS_XMLSQL_SS_TABLEdan .SQL_SS_VECTOR Ini adalah nama untuk tipe SQL, sehingga Anda meneruskannya ketika ODBC mengharapkan tipe SQL, seperti argumen ParameterType dari SQLBindParameter.
  • Tiga tipe C yang cocok untuk sisi buffer: SQL_C_SS_TIME2, SQL_C_SS_TIMESTAMPOFFSET, dan SQL_C_SS_VECTOR. Tipe SQL Server lainnya dipetakan ke tipe C ODBC standar seperti SQL_C_BINARY atau SQL_C_WCHAR, sehingga tidak memiliki padanan SQL_C_SS_*.
  • Struktur yang diikat oleh tipe SQL_C_SS_*: SQL_SS_TIME2_STRUCT, SQL_SS_TIMESTAMPOFFSET_STRUCT, dan SQL_SS_VECTOR_STRUCT.
  • Menyalin prototipe dan makro secara massal, termasuk bcp_init, bcp_bind, bcp_sendrow, bcp_batch, dan bcp_done. Opsi BCP_ENCRYPT_OFF, BCP_ENCRYPT_ON, dan BCP_ENCRYPT_STRICT hanya ada di header Windows.

Setiap platform menyertakan salinan msodbcsql.h mereka sendiri, dan tidak semuanya mendeklarasikan simbol yang sama. Struktur SQLPERF dan atribut koneksi kinerja yang mengisinya, seperti SQL_COPT_SS_PERF_DATA dan SQL_COPT_SS_PERF_QUERY, hanya ada di header Windows. Header Linux dan macOS tidak mengidentifikasinya, dan driver tidak mengumpulkan data performa di platform tersebut. Lihat Pedoman pemrograman (Linux dan macOS).

Untuk kata kunci string koneksi yang terkait dengan atribut ini, lihat DSN serta kata kunci dan atribut string koneksi. Untuk pengaturan Microsoft Entra ID, lihat Gunakan Microsoft Entra ID dengan driver ODBC. Untuk tipe vektor , lihat Tipe data vektor.

Pilih antara eksekusi asinkron dan thread

Beberapa fungsi ODBC dapat berjalan secara sinkron atau asinkron. Dalam mode sinkron, driver tidak mengembalikan kontrol sampai server menjawab. Dalam mode asinkron, driver segera mengembalikan SQL_STILL_EXECUTING, dan aplikasi mengulangi panggilan yang sama dengan argumen yang sama hingga menerima kode pengembalian yang berbeda. Kode pengembalian lain, termasuk SQL_ERROR, berarti operasi telah selesai.

Mode asinkron memiliki dua bentuk, dan Anda menggunakan salah satunya. Panggil SQLGetInfo dengan SQL_ASYNC_MODE untuk mengetahui mana yang didukung oleh driver. Akan mengembalikan SQL_AM_STATEMENT jika driver mendukung kontrol per pernyataan, SQL_AM_CONNECTION jika pengaturan berlaku untuk seluruh koneksi, atau SQL_AM_NONE jika driver sama sekali tidak menjalankan fungsi secara asinkron.

Formulir pernyataan mengaktifkan mode asinkron untuk satu handle pernyataan. Setiap pernyataan lain pada koneksi tetap sinkron, jadi Anda dapat menjalankan kedua jenis tersebut secara bersamaan:

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

Jika SQL_ASYNC_MODE mengembalikan SQL_AM_CONNECTION, atribut statement bersifat baca-saja dan panggilan ini mengembalikan SQL_ERROR dengan SQLSTATE HYC00. Gunakan formulir koneksi sebagai gantinya.

Formulir koneksi mengaktifkan mode asinkron untuk setiap handle pernyataan yang Anda alokasikan pada koneksi tersebut setelahnya. Apakah ini juga memengaruhi handle yang sudah ada ditentukan oleh driver, jadi atur ini sebelum Anda mengalokasikan pernyataan apa pun:

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

Panggilan akan kembali SQL_ERROR dengan SQLSTATE HY010 jika sebuah fungsi masih dijalankan secara asinkron pada pernyataan untuk koneksi tersebut. Kursor terbuka saja tidak akan memblokir panggilan. Passing SQL_ASYNC_ENABLE_OFF mengembalikan setiap pernyataan pada koneksi ke mode sinkron.

Untuk mengetahui berapa banyak pernyataan asinkron yang didukung driver sekaligus pada satu koneksi, hubungi SQLGetInfo dengan SQL_MAX_ASYNC_CONCURRENT_STATEMENTS. Microsoft ODBC Driver 18 untuk SQL Server mengembalikan 1, jadi rencanakan satu operasi asinkron luar biasa per koneksi dan buka lebih banyak koneksi atau gunakan thread di luar itu. Lihat Eksekusi asinkron (metode polling).

Utas adalah cara lain untuk menjaga beberapa operasi tetap berlangsung secara bersamaan. ODBC mengharuskan driver-driver pada sistem operasi multithread aman terhadap thread, sehingga sebuah thread dapat melakukan panggilan ODBC yang memblokir sementara thread-thread lain tetap berjalan. Itu menghindari loop polling dan panggilan fungsi berulang yang diperlukan dalam mode asinkron. Berikan setiap thread handle pernyataannya sendiri. Driver kemungkinan besar akan menyerialisasi dua thread yang menggunakan handle yang sama pada waktu yang sama, jadi berbagi satu thread berarti Anda kehilangan konkurensi. Lihat Multithreading. Pilih thread untuk kode baru, dan ukur beban kerja Anda sendiri sebelum mengonversi kode asinkron yang sudah berfungsi.

Di Windows, driver manager juga mendukung metode notifikasi, yang menghapus loop polling. Anda mengaitkan event Win32 dengan koneksi atau handle pernyataan. Fungsi tersebut tetap segera mengembalikan SQL_STILL_EXECUTING, dan pengelola driver memberi sinyal saat peristiwa terjadi ketika operasi selesai. Polling dinonaktifkan dalam mode ini: memanggil kembali fungsi asli akan menghasilkan SQL_ERROR dengan SQLSTATE IM017. Panggil SQLCompleteAsync untuk mengambil hasilnya saja. Ini membutuhkan driver manager versi ODBC 3.81 dan versi yang lebih baru, dan driver juga harus mendukungnya. Hubungi SQLGetInfo dengan SQL_ASYNC_NOTIFICATION untuk memeriksa. Nilai yang Anda peroleh bergantung pada versi ODBC yang dinyatakan oleh aplikasi Anda: dengan Microsoft ODBC Driver 18 untuk SQL Server, aplikasi yang menetapkan SQL_ATTR_ODBC_VERSION ke SQL_OV_ODBC3_80 akan memperoleh SQL_ASYNC_NOTIFICATION_CAPABLE, sedangkan aplikasi yang menyatakan SQL_OV_ODBC3 akan memperoleh SQL_ASYNC_NOTIFICATION_NOT_CAPABLE dari driver yang sama. Deklarasikan SQL_OV_ODBC3_80 sebelum Anda mengalokasikan koneksi. Lihat eksekusi asinkron (metode notifikasi) dan contoh metode notifikasi.

Batalkan operasi yang belum selesai

SQLCancel membatalkan operasi yang masih berjalan pada handle pernyataan. Panggil dari thread lain, atau dari loop polling, dengan meneruskan handle dari panggilan yang masih tertunda.

Gunakan SQLCancel hanya untuk itu. Untuk meninggalkan hasil yang Anda tidak ingin lagi baca, panggil SQLCloseCursor , atau SQLMoreResults sebagai gantinya.

Migrasi dari sqlncli.h ke msodbcsql.h

SQL Server Native Client sudah dipensiunkan, sehingga aplikasi yang menggunakannya harus beralih ke Microsoft ODBC Driver for SQL Server. API ini adalah API ODBC yang sama, jadi sebagian besar pekerjaan melibatkan penggantian nama input build dan nama driver dalam string koneksi.

SQL Server Native Client Microsoft ODBC Driver 18 untuk 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

Berkas header msodbcsql.h masih mendefinisikan makro nama SQLNCLI_*, sehingga kode sumber yang menggunakannya tetap dapat dikompilasi. Definisi-definisi ini dijaga oleh #ifndef __sqlncli_h__, yang berarti Anda tidak dapat memasukkan kedua header dalam satu unit terjemahan yang sama. Hapus bagian yang sqlncli.h disertakan.

Ada dua hal yang tidak terbawa:

  • Fungsi API metadata kueri terdistribusi yang mengembalikan daftar server tertaut dan katalognya tidak dideklarasikan di msodbcsql.h. Itu khusus untuk SQL Server Native Client.
  • Versi 18 mengenkripsi koneksi secara default dan memvalidasi sertifikat server. Native Client tidak melakukannya. string koneksi yang bekerja dengan Native Client dapat gagal pada koneksi pertama sampai Anda memperbaiki kepercayaan sertifikat atau mengatur Encrypt secara eksplisit. Lihat Pemecahan masalah enkripsi koneksi.

Untuk sisa perubahan dari versi 17 hingga versi 18, lihat Perbedaan versi utama.