Microsoft ODBC-illesztő az SQL Serverhez

ODBC-illesztőprogram letöltése

Az ODBC egy natív adathozzáférési alkalmazásprogramozási felület (API) C és C++ nyelven írt alkalmazások számára. A Microsoft ODBC Driver for SQL Server a következőkhöz kapcsolódik: SQL Serverhez, Azure SQL Database-hez, Azure SQL Managed Instance-hez, Azure Synapse Analyticshez és a Microsoft Fabricben lévő SQL-adatbázishoz. Az egyes illesztőprogramok által támogatott adatbázis-verziókról lásd: SQL verzió kompatibilitás.

Az alkalmazásod hívja az ODBC driver managert, amely betölti az illesztőprogramot, és továbbítja neki az ODBC hívásokat. Használd a Windows ODBC Driver Manager-et Windows-on, valamint unixODBC-t Linuxon és macOS-en.

Az ODBC-t használó egyéb nyelvek közé tartozik a COBOL, a Perl, a PHP és a Python. Az ODBC-t széles körben használják adatintegrációs helyzetekben, és a Microsoft Drivers for PHP for SQL Server ezen meghajtón alapul.

A sqlcmd ODBC változata és a bcp segédprogram ezt a meghajtót használja, de külön települnek: a mssql-tools18 csomag Linuxon és macOS-en, valamint a Microsoft Command Line Utilities Windows rendszeren. A sqlcmd Go változata nem használja ezt a drivert. A sqlcmd segítségével Transact-SQL (T-SQL) utasításokat, rendszereljárásokat és szkriptfájlokat futtathatsz. Használd a bcp-t, hogy tömegesen másolj adatokat egy SQL Server példány és egy adatfájl között, mindkét irányban.

Válassza ki a kiindulási pontot

Azure SQL üzemi alapkonfigurációja

Használd ezt a teljes C++17 programot kiindulópontként egy Azure-alapú alkalmazás számára. Csatlakozik, fut, SELECT 1ellenőrzi az eredményt, és felszabadítja az ODBC fogantyúkat. Telepítsd a Driver 18-at és a platform ODBC fejlesztői fájljait, mielőtt lefordítanád. Az előfeltételekért lásd a C- és C++-alkalmazások fejlesztése az ODBC-illesztőprogrammal című cikket.

Állítsd ODBC_CONNECTION_STRING be az alkalmazás környezetében a teljes kapcsolati karakterlánc-et. A következő példa egy rendszerhez rendelt menedzselt identitást használ. A hoszton engedélyezve kell lennie ennek az identitásnak, és az adatbázisnak hozzáférést kell biztosítania neki. A hosztigényekkel, a felhasználó által hozzárendelt identitásokkal és a helyi fejlesztési hitelesítéssel kapcsolatban lásd: A Microsoft Entra ID használata az ODBC-illesztőprogrammal.

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 olyan végpontot igényel, amely támogatja a Tabular Data Stream (TDS) 8.0-t. Ellenkező esetben használja a Encrypt=yes;TrustServerCertificate=no. Konfigurálj egy tanúsítványt, amelyben az ügyfél megbízik, és amelynek neve megegyezik a szerver nevével. A beállítással és ellenőrzéssel kapcsolatban lásd: A kapcsolattitkosítás hibakeresése.

Tartsd távol a hitelesítő adatokat a forrásfájloktól és a shell előzményeitől. A környezeti változó beállításához szükséges parancsokért lásd: A kapcsolat konfigurálása. Linuxon és macOS-en UTF-8-ként add meg az értékét. Mentsük el a következő programot odbc-baseline.cpp néven:

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

A program legfeljebb négy kapcsolati próbálkozáshoz 30 másodperces kapcsolati időkorlátot és 10 másodperces lekérdezési időkorlátot kér. A sikertelen átmeneti csatlakozási próbálkozások között 10, 20 és 40 másodpercig vár, mindegyikhez 0–250 milliszekundum véletlenszerű késleltetés társul. Ezek a korlátok nem szabnak szigorú általános határidőt a hitelesítésre. A példa a kiválasztott átmeneti kapcsolati hibákat osztályozza; a szabályzatot a munkaterheléshez igazítsa az Azure SQL átmeneti hibakatalógusával. Nem próbálja újra az alkalmazásparancsokat vagy írási műveleteket.

ConnectRetryCount és ConnectRetryIntervala kapcsolatok megbízható újracsatlakozását konfigurálja azokhoz a megfelelő kapcsolatokhoz, amelyek tétlen állapotban megszakadnak. Nem próbálják újra a kezdeti kapcsolatot, és nem játsszák újra az alkalmazásparancsokat. Tartsd rövidebbnek az inaktivitás utáni helyreállítási késleltetéseket, mint a lekérdezés időkorlátját. A minta SQLSTATE értékeket és natív hibaszámokat rögzít a kapcsolati sztringek vagy teljes diagnosztikai üzenetek helyett. Ha üzenet szövegre van szükséged hibakereséshez, rögzítsd egy védett diagnosztikai naplóba.

Építsd és futtasd a kiinduló verziót

Használj olyan fordító környezetet, amely megfelel az alkalmazásod processzorarchitektúrájának. Windows-on futtasd le a parancsokat a Developer PowerShell for Visual Studio-ban. Linuxon és macOS-en használj olyan shellt, ahol elérhető a fordító és a unixODBC fejlesztői fájljai.

cl /nologo /std:c++17 /EHsc /W4 odbc-baseline.cpp odbc32.lib
.\odbc-baseline.exe

Egy sikeres első csatlakozás a következő kimenetet nyomtatja. További diagnosztikai dokumentumok is megjelenhetnek.

event=connected attempt=1
event=ready result=1

Tisztítsd meg a ODBC_CONNECTION_STRING elemet, amikor végeztél: használd a Remove-Item Env:\ODBC_CONNECTION_STRING parancsot PowerShellben, illetve a unset ODBC_CONNECTION_STRING parancsot Bashban vagy Zsh-ben.

A rendelkezésre állási csoport figyelőihez és a feladatátvételi beállításokhoz használja a(z) High availability and disaster recovery lehetőséget.

Legfontosabb funkciók

  • Többplatformos: Ugyanaz az API Windows-on, Linuxon és macOS-en.
  • Microsoft Entra ID hitelesítés: Menedzselt identitás, szolgáltatásnév és integrált hitelesítés, valamint interaktív hitelesítés Windowson. A rendelkezésre álló módszerek a hoszt és az adatbázis konfigurációjától függnek.
  • Szigorú titkosítás: TDS 8.0 kapcsolatok teljes tanúsítvány ellenőrzéssel a 18-as verzióban és későbbi verziókban.
  • Always Encrypted: Kliensoldali titkosítás érzékeny oszlopokhoz, egyedi kulcstároló szolgáltatók támogatásával.
  • Kapcsolat-helyreállítás: Az inaktív állapotban megszakadt kapcsolat észrevétlen helyreállítása.
  • Magas elérhetőség: Elérhető csoporthallgatói támogatás .MultiSubnetFailover
  • Adatosztályozás: Érzékenységi metaadatok osztályozott oszlopokhoz.
  • Vektor adattípus: Natív támogatás a vektortípushoz .
  • Elosztott tranzakciók: XA tranzakciós támogatás a Microsoft Distributed Transaction Coordinator (MSDTC) segítségével.
  • Kísérő eszközök: sqlcmd és bcp, külön telepítve.

Első lépések

Cikk Description
ODBC-illesztőprogram letöltése az SQL Serverhez Telepítő és csomagletöltések minden támogatott illezőprogram-verzióhoz, mindhárom platformon.
C és C++ alkalmazások fejlesztése az ODBC illezserrel Melyik fejléceket kell beilleszteni, milyen sorrendben, mely könyvtárakat kapcsoljuk össze, és hogyan válasszunk aszinkron végrehajtás és szálak között.
Kapcsolódás adatbázishoz és annak lekérdezése C++ használatával Egy teljes C++ minta, amely csatlakozik, lefuttat egy lekérdezést és olvas eredményeket, így végtől végig megerősítheted a beállításodat.
Támogatási életciklus Mely illesztőprogram-verziók támogatottak még, és melyiknek mikor szűnik meg a támogatása.
Főbb verzióbeli különbségek Mi törik meg, amikor a 17-es verzióról a 18-as verzióra váltasz, kezdve a titkosítás alapértelmezett változásával.

Az illesztőprogram telepítése

Cikk Description
Rendszerkövetelmények, telepítés és illesztőprogramfájlok (Windows) Támogatta a Windows verziókat, a telepítő parancssorát a néma telepítéshez, és ahol minden driver fájl a meghajtón lekerül.
Rendszerkövetelmények (Linux és macOS) Melyik Linux disztribúciók és macOS kiadásai támogatják az egyes driver-verziókat, plusz az SQL Server verzió kompatibilitását.
Telepítsd az ODBC drivert Linuxon A csomagkezelő lépései Alpine, Debian, Red Hat, SUSE, Ubuntu és Azure Linux esetén, valamint az offline telepítés és az illesztőprogram fájljainak helye.
Telepítsd az ODBC drivert macOS-re Homebrew tap- és formula-lépések macOS-hez, beleértve a 18-as, 17-es vagy 13.1-es verzió telepítését.
Telepítsd az unixODBC illesztőprogramkezelőt (Linux és macOS) Telepítsd vagy frissítsd az unixODBC-t, az illesztőprogramkezelőt, amely betölti az ODBC illezőprogramot Linuxon és macOS-en.

Konfigurálás és csatlakoztatás

Cikk Description
A DSN és a kapcsolatkarakterlánc kulcsszavai és attribútumai A kapcsolati karakterlánc kulcsszavak, DSN bejegyzések és SQLSetConnectAttr attribútumok teljes katalógusa, mindegyikhez elfogadott értékekkel.
Kapcsolati string kulcsszavak és adatforrásnevek (Linux és macOS) A odbc.ini és odbcinst.ini hogyan definiálja a DSN-t Linuxon és macOS-en, valamint az ezen platformokra jellemző Transport Layer Security (TLS) és Transmission Control Protocol (TCP) életben tartási beállításai.
ODBC adatforrás adminisztrátor DSN (Windows) Adatforrást konfigurálj a Windows felhasználói felületén keresztül a kapcsolati sztring helyett.
Illesztőprogram-függő kapcsolatkészlet (Windows) A kapcsolati karakterlánc mely kulcsszavai és attribútumai helyeznek egy kapcsolatot külön kapcsolatkészletbe, és melyek igényelnek egy további oda-vissza kérést a visszaállításhoz.

Hitelesítés és biztonság

Cikk Description
Használd a Microsoft Entra ID-t az ODBC driverrel Minden Authentication kulcsszóérték, a felügyelt identitástól és a szolgáltatásnévtől az interaktívig és az integráltig, a mindegyikhez szükséges beállításokkal együtt.
Az Always Encrypted használata az ODBC-illesztőprogrammal Titkosítsd az érzékeny oszlopértékeket, mielőtt elküldöd őket az adatbázisba; lásd az illesztőprogram API-jának összefoglalóját és a dokumentált korlátokat.
Adatbesorolás Olvassa el a szerver által a titkosított oszlopokhoz csatolt érzékenységi címkéket, hogy az alkalmazásod érvényesítse saját adatvédelmi szabályzatát.
Integrált hitelesítést használj (Linux és macOS) Konfiguráld a Kerberost úgy, hogy egy Linux vagy macOS kliens Windows hitelesítő értékkel csatlakozhasson SQL Server bejelentkezés helyett.

Magas rendelkezésre állás és rugalmasság

Cikk Description
Kapcsolat rugalmassága Hogyan állítja helyre a ConnectRetryCount és a ConnectRetryInterval a kapcsolatot, amikor a szerver tétlen állapotban bontja azt, valamint milyen IMCxx hibákat ad vissza az illesztőprogram, amikor a helyreállítás nem lehetséges.
Magas rendelkezésre állás és vészhelyreállítás Csatlakozz egy elérhető csoporthallgatón keresztül, és használd MultiSubnetFailover , hogy a failover ne akadjon meg egy alhálózati időkorlátnál.
Használj átlátszó hálózati IP felbontást Hogyan rendezi az örökölt TransparentNetworkIPResolution tartalékmechanizmus a több Internet Protocol (IP)-cím közötti kapcsolódási kísérletek sorrendjét, és hogy a MultiSubnetFailover miért váltja fel.

Adatkezelés

Cikk Description
Vektor adattípus A vector típus csatolása, küldése és lekérése, beleértve annak natív C-beli reprezentációját és a tömeges másolás támogatását.
XA tranzakciók használata DTC-vel Regisztrálja az SQL Server-t egy elosztott tranzakcióban a Microsoft Distributed Transaction Coordinator-on keresztül Windows-on, Linuxon vagy macOS-en.
Programozási irányelvek (Linux és macOS) Találjon útmutatót Linux és macOS programozáshoz, beleértve a funkciók állapotát, a karakterkészlet megfontolásait, az OpenSSL-t és az Alpine Linuxot.

Diagnosztizálás és hibaelhárítás

Cikk Description
Kapcsolat titkosítási hibakeresés Javítsd ki a 18-as verzió által felbukkanó tanúsítvány- és titkosítási hibákat, mert alapértelmezés szerint titkosít.
Adathozzáférési követés (Linux és macOS) Kapcsold be a driver trace-t, és rögzíts egy naplófájlt, amikor látod, milyen hívásokat hajt végre az alkalmazásod.
Ismert problémák (Linux és macOS) Megerősített hibák és azok megoldásai. Mielőtt támogatási keresetet nyújtanál be, nézd meg ide.
Gyakran ismételt kérdések (Linux és macOS) Rövid válaszok azokra a kérdésekre, amelyek leggyakrabban felmerülnek a driverrel kapcsolatban Linux és macOS rendszeren.

Kiadási jegyzetek és hibajavítások

Cikk Description
Kiadási jegyzetek Windows-hoz Új funkciók, viselkedésváltozások és javítások minden Windows illepőprogram-kiadásban.
Kiadási jegyzetek Linux és macOS számára Új funkciók, viselkedésváltozások és javítások minden Linux és macOS illezőgép kiadásban.
Kiadási jegyzetek az SQL Server eszközökhöz Változások a sqlcmd és bcp segédeszközökben, amelyek külön telepíthetők a drivertől Linuxon és macOS-en.

Reference

Cikk Description
ODBC illesztőprogram Windows rendszerhez Verzióról verzióra összefoglaló arról, mit támogat a meghajtó Windows-on, valamint a Windows-specifikus cikkek indexe.
Az ODBC illezser jellemzői a Windows-on Melyik kiadás vezette be az egyes Windows funkciókat, valamint a hozzá tartozó viselkedésváltozásokat.

Szolgáltatás igénylése

Funkció kéréséhez ötletet küldj be az SQL Server visszajelzésével.