Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
ODBC adalah antarmuka pemrograman aplikasi akses data asli (API) untuk aplikasi yang ditulis dalam bahasa C dan C++. Microsoft ODBC Driver untuk SQL Server terhubung ke SQL Server, Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics, dan database SQL Microsoft Fabric. Untuk versi database yang didukung setiap rilis driver, lihat kompatibilitas versi SQL.
Aplikasi Anda memanggil manajer driver ODBC, yang memuat driver dan meneruskan panggilan ODBC kepadanya. Gunakan Windows ODBC Driver Manager di Windows dan unixODBC di Linux dan macOS.
Bahasa lain yang dapat menggunakan ODBC termasuk COBOL, Perl, PHP, dan Python. ODBC banyak digunakan dalam skenario integrasi data, dan Microsoft Drivers untuk PHP untuk SQL Server dibangun di atas driver ini.
Varian ODBC dari sqlcmd dan utilitas bcp menggunakan driver ini, tetapi mereka menginstal secara terpisah: paket mssql-tools18 di Linux dan macOS, serta Microsoft Command Line Utilities di Windows. Varian Go dari sqlcmd tidak menggunakan driver ini. Gunakan sqlcmd untuk menjalankan pernyataan Transact-SQL (T-SQL), prosedur sistem, dan file skrip. Gunakan bcp untuk menyalin data secara massal antara instance SQL Server dan file data, dalam kedua arah.
Pilih titik awal Anda
- Untuk menginstal driver, lihat Persyaratan sistem, penginstalan, dan file driver untuk Windows, atau Menginstal driver ODBC di Linux, Menginstal driver ODBC di macOS, dan Menginstal pengelola driver unixODBC.
- Untuk menulis aplikasi pertama Anda, buka Connect to and query database dengan C++. Untuk opsi nama sumber data (DSN) dan string koneksi, gunakan kata kunci dan atribut DSN dan string koneksi. Jika compiler Anda tidak menemukan header atau build Anda tidak mau terhubung, buka Kembangkan aplikasi C dan C++ dengan driver ODBC.
- Untuk terhubung ke Azure SQL dengan autentikasi tanpa kata sandi, buka Gunakan Microsoft Entra ID dengan driver ODBC.
- Untuk membuat aplikasi yang sudah ada tahan terhadap kegagalan sementara, buka Ketahanan Koneksi dan Ketersediaan Tinggi serta pemulihan bencana.
- Untuk upgrade dari versi 17, buka Perbedaan versi utama dan pemecahan masalah enkripsi koneksi.
- Untuk mendiagnosis masalah koneksi atau kueri, buka Pemecahan masalah enkripsi koneksi dan Masalah yang diketahui (Linux dan macOS).
Garis besar produksi untuk Azure SQL
Gunakan program C++17 lengkap ini sebagai titik awal untuk aplikasi yang dihosting Azure. Membuat koneksi, menjalankan SELECT 1, memeriksa hasilnya, dan melepaskan handle ODBC. Instal Driver 18 dan file pengembangan ODBC milik platform sebelum Anda membangunnya. Untuk prasyarat, lihat Mengembangkan aplikasi C dan C++ dengan driver ODBC.
Atur ODBC_CONNECTION_STRING di lingkungan aplikasi menjadi string koneksi lengkap Anda. Contoh berikut menggunakan identitas terkelola yang ditetapkan oleh sistem. Host harus sudah mengaktifkan identitas tersebut, dan database harus memberinya akses. Untuk persyaratan host, identitas yang diberikan pengguna, dan autentikasi pengembangan lokal, lihat Gunakan Microsoft Entra ID dengan driver ODBC.
Driver={ODBC Driver 18 for SQL Server};Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=ActiveDirectoryMsi;Encrypt=strict;ConnectRetryCount=3;ConnectRetryInterval=2;
Encrypt=strict memerlukan endpoint yang mendukung Tabular Data Stream (TDS) 8.0. Jika tidak, gunakan Encrypt=yes;TrustServerCertificate=no. Konfigurasikan sertifikat yang dipercaya klien dan namanya sesuai dengan nama server. Untuk pengaturan dan verifikasi, lihat Pemecahan masalah enkripsi koneksi.
Jauhkan kredensial dari file sumber dan riwayat shell. Untuk perintah guna menetapkan variabel lingkungan, lihat Konfigurasikan koneksi. Di Linux dan macOS, berikan nilainya sebagai UTF-8. Simpan program berikut sebagai odbc-baseline.cpp:
#ifdef _WIN32
#include <windows.h>
#else
#include <iconv.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <random>
#include <stdexcept>
#include <string>
#include <thread>
#include <vector>
struct Handles {
SQLHENV env = SQL_NULL_HENV;
SQLHDBC dbc = SQL_NULL_HDBC;
SQLHSTMT stmt = SQL_NULL_HSTMT;
bool connected = false;
~Handles() {
if (stmt) SQLFreeHandle(SQL_HANDLE_STMT, stmt);
if (connected) SQLDisconnect(dbc);
if (dbc) SQLFreeHandle(SQL_HANDLE_DBC, dbc);
if (env) SQLFreeHandle(SQL_HANDLE_ENV, env);
}
};
bool logDiagnostics(SQLSMALLINT type, SQLHANDLE handle) {
bool retry = false;
bool permanent = false;
for (SQLSMALLINT record = 1; ; ++record) {
SQLWCHAR state[6] = {};
SQLWCHAR message[1024] = {};
SQLINTEGER native = 0;
SQLRETURN rc = SQLGetDiagRecW(type, handle, record, state, &native,
message, 1024, nullptr);
if (rc == SQL_NO_DATA) break;
if (!SQL_SUCCEEDED(rc)) {
std::cerr << "event=diagnostics_failed rc=" << rc << '\n';
return false;
}
std::string sqlstate;
for (int i = 0; i < 5; ++i) {
sqlstate += static_cast<char>(state[i]);
}
std::cerr << "event=odbc_diagnostic sqlstate=" << sqlstate
<< " native_error=" << native << '\n';
permanent |= sqlstate.substr(0, 2) == "28" ||
sqlstate.substr(0, 2) == "IM" ||
sqlstate == "HY024" || sqlstate == "HY092";
retry |= sqlstate == "08S01" || sqlstate == "HYT00" ||
sqlstate == "HYT01";
switch (native) {
case 10928: case 10929: case 10936:
case 40197: case 40501: case 40613:
case 49918: case 49919: case 49920:
retry = true;
}
}
return retry && !permanent;
}
void requireSuccess(SQLRETURN rc, SQLSMALLINT type, SQLHANDLE handle,
const char* operation) {
if (rc == SQL_SUCCESS) return;
logDiagnostics(type, handle);
if (!SQL_SUCCEEDED(rc)) throw std::runtime_error(operation);
}
std::vector<SQLWCHAR> readConnectionString() {
static_assert(sizeof(SQLWCHAR) == 2, "Use a driver manager with 16-bit SQLWCHAR");
#ifdef _WIN32
size_t length = 0;
if (_wgetenv_s(&length, nullptr, 0, L"ODBC_CONNECTION_STRING") != 0 ||
length == 0) {
throw std::runtime_error("ODBC_CONNECTION_STRING is required");
}
std::vector<wchar_t> raw(length);
if (_wgetenv_s(&length, raw.data(), raw.size(), L"ODBC_CONNECTION_STRING") != 0) {
throw std::runtime_error("Cannot read ODBC_CONNECTION_STRING");
}
std::vector<SQLWCHAR> result(raw.begin(), raw.end() - 1);
#else
const char* raw = std::getenv("ODBC_CONNECTION_STRING");
if (!raw) throw std::runtime_error("ODBC_CONNECTION_STRING is required");
iconv_t converter = iconv_open("UTF-16LE", "UTF-8");
if (converter == reinterpret_cast<iconv_t>(-1)) {
throw std::runtime_error("Cannot create UTF-8 converter");
}
size_t inputBytes = std::strlen(raw);
std::vector<SQLWCHAR> result(inputBytes + 1);
char* input = const_cast<char*>(raw);
char* output = reinterpret_cast<char*>(result.data());
size_t outputBytes = result.size() * sizeof(SQLWCHAR);
const size_t capacity = outputBytes;
size_t status = iconv(converter, &input, &inputBytes, &output, &outputBytes);
int closeStatus = iconv_close(converter);
if (status == static_cast<size_t>(-1) || inputBytes != 0 || closeStatus != 0) {
throw std::runtime_error("ODBC_CONNECTION_STRING must be valid UTF-8");
}
result.resize((capacity - outputBytes) / sizeof(SQLWCHAR));
#endif
if (result.empty() || result.size() >= 32767) {
throw std::runtime_error("Invalid ODBC_CONNECTION_STRING length");
}
result.push_back(0);
return result;
}
void connectWithRetry(SQLHDBC dbc, std::vector<SQLWCHAR>& connectionString) {
constexpr int maxAttempts = 4;
std::mt19937 random{std::random_device{}()};
std::uniform_int_distribution<int> jitter{0, 250};
for (int attempt = 1; attempt <= maxAttempts; ++attempt) {
requireSuccess(SQLSetConnectAttr(
dbc, SQL_ATTR_LOGIN_TIMEOUT,
reinterpret_cast<SQLPOINTER>(std::uintptr_t{30}), 0),
SQL_HANDLE_DBC, dbc, "Set login timeout");
SQLRETURN rc = SQLDriverConnectW(
dbc, nullptr, connectionString.data(), SQL_NTS,
nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc)) {
if (rc == SQL_SUCCESS_WITH_INFO) logDiagnostics(SQL_HANDLE_DBC, dbc);
std::cout << "event=connected attempt=" << attempt << '\n';
return;
}
bool transient = logDiagnostics(SQL_HANDLE_DBC, dbc);
if (!transient || attempt == maxAttempts) {
throw std::runtime_error("Connect failed");
}
auto delay = std::chrono::milliseconds{
(1 << (attempt - 1)) * 10000 + jitter(random)};
std::cerr << "event=connect_retry attempt=" << attempt
<< " delay_ms=" << delay.count() << '\n';
std::this_thread::sleep_for(delay);
}
}
int main() {
try {
auto connectionString = readConnectionString();
Handles handles;
if (!SQL_SUCCEEDED(SQLAllocHandle(
SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handles.env))) {
throw std::runtime_error("Allocate environment");
}
requireSuccess(SQLSetEnvAttr(
handles.env, SQL_ATTR_ODBC_VERSION,
reinterpret_cast<SQLPOINTER>(std::uintptr_t{SQL_OV_ODBC3}), 0),
SQL_HANDLE_ENV, handles.env, "Set ODBC version");
requireSuccess(SQLAllocHandle(SQL_HANDLE_DBC, handles.env, &handles.dbc),
SQL_HANDLE_ENV, handles.env, "Allocate connection");
connectWithRetry(handles.dbc, connectionString);
handles.connected = true;
requireSuccess(SQLAllocHandle(SQL_HANDLE_STMT, handles.dbc, &handles.stmt),
SQL_HANDLE_DBC, handles.dbc, "Allocate statement");
requireSuccess(SQLSetStmtAttr(
handles.stmt, SQL_ATTR_QUERY_TIMEOUT,
reinterpret_cast<SQLPOINTER>(std::uintptr_t{10}), 0),
SQL_HANDLE_STMT, handles.stmt, "Set query timeout");
SQLWCHAR query[] = {'S', 'E', 'L', 'E', 'C', 'T', ' ', '1', 0};
requireSuccess(SQLExecDirectW(handles.stmt, query, SQL_NTS),
SQL_HANDLE_STMT, handles.stmt, "Execute probe");
requireSuccess(SQLFetch(handles.stmt),
SQL_HANDLE_STMT, handles.stmt, "Fetch probe");
SQLINTEGER value = 0;
SQLLEN indicator = 0;
requireSuccess(SQLGetData(handles.stmt, 1, SQL_C_SLONG,
&value, sizeof(value), &indicator),
SQL_HANDLE_STMT, handles.stmt, "Read probe");
if (indicator == SQL_NULL_DATA || value != 1) {
throw std::runtime_error("Unexpected probe result");
}
std::cout << "event=ready result=" << value << '\n';
return 0;
} catch (const std::exception& error) {
std::cerr << "event=failed operation=\"" << error.what() << "\"\n";
return 1;
}
}
Program meminta timeout koneksi selama 30 detik untuk setiap dari maksimal empat percobaan koneksi dan timeout kueri selama 10 detik. Di antara upaya koneksi transien yang gagal, mesin menunggu 10, 20, dan 40 detik, masing-masing dengan 0 hingga 250 milidetik jitter acak. Batasan-batasan ini tidak memberlakukan tenggat waktu yang ketat untuk autentikasi. Contoh mengklasifikasikan kesalahan koneksi transient yang dipilih; sesuaikan kebijakan dengan beban kerja Anda dengan katalog kesalahan transient fault Azure SQL. Tidak mencoba ulang perintah aplikasi atau operasi tulis.
ConnectRetryCount dan ConnectRetryInterval mengonfigurasi ketahanan koneksi untuk koneksi yang memenuhi syarat yang terputus saat tidak aktif. Mereka tidak mencoba ulang koneksi awal atau mengirim ulang perintah aplikasi. Jaga agar penundaan pemulihan idle lebih singkat daripada timeout kueri Anda. Contoh mencatat nilai SQLSTATE dan nomor error native daripada string koneksi atau pesan diagnostik lengkap. Jika Anda membutuhkan teks pesan untuk pemecahan masalah, catat dalam log diagnostik yang dilindungi.
Bangun dan jalankan baseline
Gunakan lingkungan kompiler yang sesuai dengan arsitektur prosesor aplikasi Anda. Di Windows, jalankan perintah di Developer PowerShell untuk Visual Studio. Di Linux dan macOS, gunakan shell dengan compiler dan file pengembangan unixODBC yang tersedia.
cl /nologo /std:c++17 /EHsc /W4 odbc-baseline.cpp odbc32.lib
.\odbc-baseline.exe
Setelah koneksi pertama berhasil, output berikut akan ditampilkan. Catatan diagnostik tambahan juga mungkin muncul.
event=connected attempt=1
event=ready result=1
Bersihkan ODBC_CONNECTION_STRING saat selesai: gunakan Remove-Item Env:\ODBC_CONNECTION_STRING di PowerShell, atau unset ODBC_CONNECTION_STRING di Bash atau Zsh.
Untuk pendengar grup ketersediaan dan pengaturan failover, gunakan High availability and disaster recovery.
Fitur utama
- Multiplatform: API yang sama di Windows, Linux, dan macOS.
- Autentikasi Microsoft Entra ID: Identitas terkelola, service principal, dan autentikasi terintegrasi, serta autentikasi interaktif di Windows. Metode yang tersedia bergantung pada konfigurasi host dan basis data.
- Enkripsi ketat: Koneksi TDS 8.0 dengan validasi sertifikat penuh pada versi 18 dan versi berikutnya.
- Selalu Terenkripsi: Enkripsi sisi klien untuk kolom sensitif, dengan dukungan untuk penyedia keystore kustom.
- Ketahanan koneksi: Pemulihan transparan dari koneksi yang terputus saat tidak aktif.
-
Ketersediaan tinggi: Dukungan pendengar grup ketersediaan dengan
MultiSubnetFailover. - Klasifikasi data: Metadata sensitivitas untuk kolom yang diklasifikasikan.
- Tipe data vektor: Dukungan native untuk tipe vektor .
- Transaksi terdistribusi: Dukungan transaksi XA melalui Koordinator Transaksi Terdistribusi Microsoft (MSDTC).
- Alat pendamping: sqlcmd dan bcp, diinstal secara terpisah.
Get started
| Article | Deskripsi |
|---|---|
| Unduh ODBC Driver untuk SQL Server | Instalasi dan unduhan paket untuk setiap versi driver yang didukung, di ketiga platform. |
| Kembangkan aplikasi C dan C++ dengan driver ODBC | Header mana yang harus disertakan, dalam urutan apa, pustaka mana yang akan dihubungkan, dan bagaimana memilih antara eksekusi asinkron dan thread. |
| Hubungkan ke dan kueri database dengan C++ | Contoh C++ lengkap yang terhubung, menjalankan kueri, dan membaca hasil, sehingga Anda dapat mengonfirmasi pengaturan Anda secara end-to-end. |
| Siklus hidup dukungan | Versi driver mana yang masih didukung dan tanggal berakhirnya dukungan untuk masing-masing versi. |
| Perbedaan versi utama | Apa yang rusak saat Anda berpindah dari versi 17 ke versi 18, dimulai dengan perubahan default enkripsi. |
Pasang driver
| Article | Deskripsi |
|---|---|
| Persyaratan sistem, instalasi, dan file driver (Windows) | Versi Windows yang didukung, baris perintah penginstal untuk penerapan tanpa interaksi, dan lokasi setiap file driver di disk. |
| Persyaratan sistem (Linux dan macOS) | Distribusi Linux dan rilis macOS mana yang didukung oleh setiap versi driver, ditambah kompatibilitas versi SQL Server. |
| Instal driver ODBC di Linux | Langkah-langkah pengelola paket untuk Alpine, Debian, Red Hat, SUSE, Ubuntu, dan Azure Linux, serta instalasi offline dan lokasi file driver. |
| Instal driver ODBC di macOS | Langkah-langkah Homebrew tap dan formula untuk macOS, termasuk cara menginstal versi 18, 17, atau 13.1. |
| Instal pengelola driver unixODBC (Linux dan macOS) | Instal atau tingkatkan unixODBC, pengelola driver yang memuat driver ODBC di Linux dan macOS. |
Mengonfigurasi dan menyambungkan
| Article | Deskripsi |
|---|---|
| DSN dan kata kunci serta atribut string koneksi | Katalog lengkap kata kunci string koneksi, entri DSN, dan atribut SQLSetConnectAttr, beserta nilai yang diterima untuk masing-masing. |
| Kata kunci string koneksi dan nama sumber data (Linux dan macOS) | Bagaimana odbc.ini dan odbcinst.ini mendefinisikan DSN di Linux dan macOS, serta pengaturan Transport Layer Security (TLS) dan Transmission Control Protocol (TCP) keep-alive yang spesifik untuk platform tersebut. |
| Administrator Sumber Data ODBC DSN (Windows) | Konfigurasikan sumber data melalui antarmuka pengguna Windows, bukan string koneksi. |
| Pooling koneksi berdasarkan driver (Windows) | Kata kunci dan atribut string koneksi mana yang menempatkan koneksi ke poolnya sendiri, dan mana yang membutuhkan biaya perjalanan pulang-pergi ekstra untuk direset. |
Autentikasi dan amankan
| Article | Deskripsi |
|---|---|
| Gunakan Microsoft Entra ID dengan driver ODBC | Setiap nilai kata kunci Authentication, dari managed identity dan service principal hingga interaktif dan terpadu, beserta pengaturan yang diperlukan untuk masing-masing. |
| Gunakan Selalu Terenkripsi dengan driver ODBC | Enkripsikan nilai kolom sensitif sebelum mengirimkannya ke database, dengan ringkasan API driver dan keterbatasan yang terdokumentasi. |
| Klasifikasi data | Baca label sensitivitas yang dilampirkan server pada kolom rahasia, sehingga aplikasi Anda dapat menegakkan kebijakan perlindungan data sendiri. |
| Gunakan autentikasi terintegrasi (Linux dan macOS) | Konfigurasikan Kerberos agar klien Linux atau macOS dapat terhubung dengan kredensial Windows daripada login SQL Server. |
Ketersediaan dan ketahanan tinggi
| Article | Deskripsi |
|---|---|
| Ketahanan koneksi | Bagaimana ConnectRetryCount dan ConnectRetryInterval memulihkan koneksi ketika server memutus koneksi tersebut saat tidak aktif, dan IMCxx kesalahan yang dikembalikan driver ketika pemulihan tidak dimungkinkan. |
| Ketersediaan tinggi dan pemulihan bencana | Hubungkan melalui listener grup ketersediaan dan gunakan MultiSubnetFailover agar failover tidak tersendat karena waktu tunggu subnet. |
| Gunakan resolusi IP jaringan yang transparan | Bagaimana mekanisme fallback legacy TransparentNetworkIPResolution menentukan urutan upaya koneksi di beberapa alamat Internet Protocol (IP), dan mengapa MultiSubnetFailover menggantikannya. |
Bekerja dengan data
| Article | Deskripsi |
|---|---|
| Jenis data vektor | Ikat, kirim, dan ambil tipe vektor, termasuk representasi C aslinya dan dukungan penyalinan massal. |
| Gunakan transaksi XA dengan DTC | Daftarkan SQL Server dalam transaksi terdistribusi melalui Koordinator Transaksi Terdistribusi Microsoft di Windows, Linux, atau macOS. |
| Pedoman pemrograman (Linux dan macOS) | Temukan panduan pemrograman Linux dan macOS, termasuk status fitur, pertimbangan set karakter, OpenSSL, dan Alpine Linux. |
Mendiagnosis dan memecahkan masalah
| Article | Deskripsi |
|---|---|
| Pemecahan masalah enkripsi koneksi | Perbaiki kesalahan sertifikat dan enkripsi yang ditampilkan oleh versi 18 karena menggunakan enkripsi secara default. |
| Pelacakan akses data (Linux dan macOS) | Aktifkan driver tracing dan tangkap file log saat Anda perlu melihat panggilan yang sebenarnya dilakukan aplikasi Anda. |
| Masalah yang diketahui (Linux dan macOS) | Cacat yang dikonfirmasi dan solusi alternatifnya. Periksa di sini sebelum Anda mengajukan permintaan dukungan. |
| Pertanyaan yang sering diajukan (Linux dan macOS) | Jawaban singkat untuk pertanyaan yang paling sering muncul tentang driver di Linux dan macOS. |
Catatan rilis dan perbaikan bug
| Article | Deskripsi |
|---|---|
| Catatan rilis untuk Windows | Fitur baru, perubahan perilaku, dan perbaikan di setiap rilis driver Windows. |
| Catatan rilis untuk Linux dan macOS | Fitur baru, perubahan perilaku, dan perbaikan di setiap rilis driver Linux dan macOS. |
| Catatan rilis untuk alat SQL Server | Perubahan pada utilitas sqlcmd dan bcp , yang diinstal terpisah dari driver di Linux dan macOS. |
Reference
| Article | Deskripsi |
|---|---|
| Driver ODBC di Windows | Ringkasan versi demi versi tentang apa yang didukung driver di Windows, serta indeks artikel khusus Windows. |
| Fitur driver ODBC di Windows | Rilis mana yang memperkenalkan setiap fitur Windows, plus perubahan perilaku yang menyertainya. |
Meminta fitur
Untuk meminta fitur, kirimkan ide melalui umpan balik SQL Server.
Konten terkait
- Referensi Programmer ODBC: Spesifikasi API ODBC yang diimplementasikan oleh driver ini, didokumentasikan secara terpisah dari driver.
- Fitur Native Client SQL Server: Konteks API historis. Periksa dokumentasi driver saat ini untuk dukungan platform, autentikasi, dan perilaku enkripsi. Panduan Native Client dan OLE DB tidak menunjukkan dukungan driver ODBC saat ini.
- utilitas bcp: Utilitas salinan massal, diinstal terpisah dari driver.
- utilitas sqlcmd: Utilitas kueri baris perintah, diinstal secara terpisah dari driver.
- Matriks dukungan fitur driver
- Blog Driver SQL Server