Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A következőkre vonatkozik:SQL Server
Azure SQL Database
Ebben a gyorsindításban C++ konzol alkalmazást építesz Windows-on, Linuxon vagy macOS-en. Az alkalmazás az Microsoft ODBC Driver 18 for SQL Server segítségével csatlakozik egy AdventureWorksLT adatbázishoz, egy lekérdezési paramétert köt, lefuttatja a lekérdezést, és felolvassa az eredménysorokat.
Prerequisites
- Microsoft ODBC Driver 18 for SQL Server. Telepítsd a drivert Windows-ra, Linuxra vagy macOS-re.
- Egy C++17 fordító és a platform ODBC fejlesztői fájljai:
- Windows-on telepítsd a Visual Studio 2022-t vagy a Build Tools for Visual Studio 2022-t a C++ munkaterheléssel rendelkező asztali fejlesztéssel. A Windows SDK tartalmazza az ODBC-fejléceket és a(z)
odbc32.libelemet. - Linuxon telepíts egy C++ fordítót és az unixODBC fejlesztő csomagot a disztribúciódhoz. A csomag tartalmazza az ODBC fejlécfájlokat és a(z)
libodbcelemet. - macOS-en telepítsd az Xcode parancssori eszközöket és az unixODBC-t a Homebrew-ből.
- Windows-on telepítsd a Visual Studio 2022-t vagy a Build Tools for Visual Studio 2022-t a C++ munkaterheléssel rendelkező asztali fejlesztéssel. A Windows SDK tartalmazza az ODBC-fejléceket és a(z)
- Egy adatbázis Azure SQL Database-ben vagy SQL Server-ben, amely tartalmazza a
AdventureWorksLTmintaadatokat. Azure SQL Database esetén válaszd a Sample adatforrást, amikor egyetlen adatbázist hozol létre. SQL Server esetén állíts vissza egyAdventureWorksLTbiztonsági mentést az AdventureWorks mintaadatbázisaiból.
Ellenőrizd a sofőröt
Erősítse meg, hogy a driver manager megtalálja a Microsoft ODBC Driver 18-at az SQL Server-hez.
Futtassa ezt a parancsot a PowerShellben:
Get-OdbcDriver -Name "ODBC Driver 18 for SQL Server"
Minden parancsnak fel kell tüntetnie ODBC Driver 18 for SQL Server. Ha a meghajtó nincs feltüntetve, telepítsd újra, mielőtt folytatnád.
Konfiguráld a kapcsolatot
Az alkalmazás a környezeti változóból olvassa fel a teljes kapcsolati karakterlánc-etODBC_CONNECTION_STRING. Nem jeleníti meg a kapcsolati karakterlánc-et, és nem fogadja el parancssori argumentumként.
Használj egy Driver 18 kapcsolati karakterlánc-et, amely érvényes az adatbázisodhoz és a hitelesítési módszeredhez. Az alábbi SQL hitelesítési példa működik Windows-on, Linuxon és macOS-en, amikor az adatbázis lehetővé teszi az SQL hitelesítést:
Driver={ODBC Driver 18 for SQL Server};Server=tcp:<server>,1433;Database=<database>;UID=<user_id>;PWD=<password>;Encrypt=yes;TrustServerCertificate=no;
A Microsoft Entra hitelesítési lehetőségeiről lásd a következőt: A Microsoft Entra ID használata az ODBC-illesztőprogrammal. Minden támogatott beállításért lásd a DSN és a kapcsolati karakterlánc kulcsszavakat és attribútumokat.
A Microsoft ODBC Driver 18 alapértelmezetten engedélyezi a titkosítást. Határozd Encrypt=yes meg, hogy a kérelem követelménye egyértelmű legyen. Tartsd TrustServerCertificate=no a gyártásban, hogy az illesztőprogram érvényesítse a szerver tanúsítványt. A tanúsítványnak a szerver nevét és láncát össze kell egyeztetnie egy olyan tanúsító hatósággal, amelyben az ügyfél megbízik. Konfigurációs útmutatásért lásd: Tanúsítvány validációs hibák.
Figyelmeztetés
TrustServerCertificate=yes kihagyja a tanúsítvány érvényesítését. Csak izolált helyi fejlesztéshez használd, miközben egy olyan tanúsítványt konfigurálsz, amit az ügyfél megbízik. Ne használja éles környezetben.
Állítsd be a környezeti változót anélkül, hogy hozzáadnád a kapcsolati karakterlánc-et a shell történetedhez.
Nyissa meg a Developer PowerShellt a VS 2022-höz. Futtatd ezeket a parancsokat, majd illesztsd be a kapcsolati karakterlánc-et a prompthoz:
$secureConnectionString = Read-Host "ODBC connection string" -AsSecureString
$env:ODBC_CONNECTION_STRING = [System.Net.NetworkCredential]::new(
"", $secureConnectionString).Password
$secureConnectionString = $null
Egy környezeti változó távol tartja a kapcsolati karakterlánc szövegét a forrásfájltól, de a folyamat és annak gyermekfolyamatai el tudják olvasni azt. Termelési alkalmazásokhoz használd a Microsoft Entra hitelesítést, ahol lehetséges, és futásidőben szerezz titkokat egy biztonságos tárolóból.
Az alkalmazás létrehozása
Hozz létre egy projektkönyvtárat, majd lépj be abba:
Hozzon létre egy
odbc-quickstart.cppnevű fájlt a következő kóddal:#ifdef _WIN32 #include <windows.h> #endif #include <sql.h> #include <sqlext.h> #include <sqltypes.h> #include <cstdlib> #include <iomanip> #include <iostream> #include <string> #include <string_view> std::string ReadEnvironmentVariable(const char* name) { #ifdef _WIN32 char* value = nullptr; std::size_t length = 0; if (_dupenv_s(&value, &length, name) != 0 || value == nullptr) return {}; std::string result(value); std::free(value); return result; #else const char* value = std::getenv(name); return value == nullptr ? std::string{} : value; #endif } bool PrintDiagnostics(SQLSMALLINT handleType, SQLHANDLE handle) { bool dataTruncated = false; SQLCHAR state[6]; SQLINTEGER nativeError; SQLCHAR message[SQL_MAX_MESSAGE_LENGTH]; SQLSMALLINT messageLength; for (SQLSMALLINT record = 1; SQL_SUCCEEDED(SQLGetDiagRec(handleType, handle, record, state, &nativeError, message, sizeof(message), &messageLength)); ++record) { std::cerr << '[' << state << "] (" << nativeError << ") " << message << '\n'; if (std::string_view(reinterpret_cast<const char*>(state), 5) == "01004") dataTruncated = true; } return dataTruncated; } bool Succeeded(SQLRETURN result, SQLSMALLINT handleType, SQLHANDLE handle, bool* dataTruncated = nullptr) { if (result == SQL_SUCCESS) return true; const bool diagnosticReportsTruncation = PrintDiagnostics(handleType, handle); if (dataTruncated != nullptr) *dataTruncated = diagnosticReportsTruncation; return result == SQL_SUCCESS_WITH_INFO; } struct OdbcHandles { SQLHENV environment = SQL_NULL_HENV; SQLHDBC connection = SQL_NULL_HDBC; SQLHSTMT statement = SQL_NULL_HSTMT; ~OdbcHandles() { if (statement != SQL_NULL_HSTMT) SQLFreeHandle(SQL_HANDLE_STMT, statement); if (connection != SQL_NULL_HDBC) { SQLDisconnect(connection); SQLFreeHandle(SQL_HANDLE_DBC, connection); } if (environment != SQL_NULL_HENV) SQLFreeHandle(SQL_HANDLE_ENV, environment); } }; int main() { std::string connectionString = ReadEnvironmentVariable("ODBC_CONNECTION_STRING"); if (connectionString.empty()) { std::cerr << "Set ODBC_CONNECTION_STRING before running.\n"; return 1; } OdbcHandles handles; SQLRETURN result = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handles.environment); if (!Succeeded(result, SQL_HANDLE_ENV, handles.environment)) { std::cerr << "Unable to allocate an ODBC environment handle.\n"; return 1; } result = SQLSetEnvAttr( handles.environment, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3_80), 0); if (!Succeeded(result, SQL_HANDLE_ENV, handles.environment)) return 1; result = SQLAllocHandle( SQL_HANDLE_DBC, handles.environment, &handles.connection); if (!Succeeded(result, SQL_HANDLE_ENV, handles.environment)) return 1; result = SQLDriverConnect( handles.connection, nullptr, reinterpret_cast<SQLCHAR*>(connectionString.data()), SQL_NTS, nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT); if (!Succeeded(result, SQL_HANDLE_DBC, handles.connection)) return 1; result = SQLAllocHandle( SQL_HANDLE_STMT, handles.connection, &handles.statement); if (!Succeeded(result, SQL_HANDLE_DBC, handles.connection)) return 1; SQLINTEGER minimumProductId = 0; SQLLEN minimumProductIdLength = 0; result = SQLBindParameter( handles.statement, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 10, 0, &minimumProductId, 0, &minimumProductIdLength); if (!Succeeded(result, SQL_HANDLE_STMT, handles.statement)) return 1; SQLCHAR query[] = "SELECT TOP (5) ProductID, Name " "FROM SalesLT.Product " "WHERE ProductID > ? " "ORDER BY ProductID;"; result = SQLExecDirect(handles.statement, query, SQL_NTS); if (!Succeeded(result, SQL_HANDLE_STMT, handles.statement)) return 1; std::cout << "Product ID Name\n" << "---------- ----\n"; while ((result = SQLFetch(handles.statement)) != SQL_NO_DATA) { if (!Succeeded(result, SQL_HANDLE_STMT, handles.statement)) return 1; SQLINTEGER productId = 0; SQLLEN productIdLength = 0; SQLCHAR productName[256] = {}; SQLLEN productNameLength = 0; result = SQLGetData( handles.statement, 1, SQL_C_SLONG, &productId, sizeof(productId), &productIdLength); if (!Succeeded(result, SQL_HANDLE_STMT, handles.statement)) return 1; bool productNameTruncated = false; result = SQLGetData( handles.statement, 2, SQL_C_CHAR, productName, sizeof(productName), &productNameLength); if (!Succeeded(result, SQL_HANDLE_STMT, handles.statement, &productNameTruncated)) return 1; std::string productNameText; if (productNameLength == SQL_NULL_DATA) { productNameText = "<NULL>"; } else if (productNameTruncated || productNameLength > static_cast<SQLLEN>(sizeof(productName) - 1)) { std::cerr << "Product name was truncated; no partial value was printed.\n"; return 1; } else if (productNameLength == SQL_NO_TOTAL) { std::cerr << "Product name length is unknown; no value was printed.\n"; return 1; } else if (productNameLength < 0) { std::cerr << "The driver returned an invalid product-name length.\n"; return 1; } else if (productNameLength == 0) { productNameText = "<empty>"; } else { productNameText.assign( reinterpret_cast<const char*>(productName), static_cast<std::size_t>(productNameLength)); } std::cout << std::left << std::setw(12) << productId << productNameText << '\n'; } return 0; }
Az alkalmazás csak a szabványos ODBC API-t használja, így tartalmazza a driver-manager fejléceket és a vezető-menedzser könyvtárhoz vezető linkeket. A kapcsolati karakterlánc futásidőben kiválasztja a Microsoft ODBC Driver 18-at az SQL Server számára.
SQL_DRIVER_NOPROMPT megakadályozza SQLDriverConnect , hogy konfigurációs párbeszédet nyissanak. Ha a kapcsolati karakterlánc hiányos, a hívás hibát ad vissza, és az alkalmazás minden diagnosztikai rekordot kinyomtat. Az alkalmazás diagnosztikát is nyomtat, amikor egy ellenőrzött ODBC-hívás visszatér SQL_SUCCESS_WITH_INFO értékkel, ami azt jelenti, hogy a hívás sikeres volt, de figyelmeztetéssel tért vissza.
A lekérdezés a elemet SQL Server 0 paraméterként köti, beolvassa az első öt terméket a SalesLT.Product elemből, és SQLGetData-lel lekéri az egyes termékek azonosítóját és nevét. Terméknév esetén az alkalmazás a <empty> helyén SQL_NULL_DATA-t, nulla hosszúságú érték esetén pedig <NULL>-t jelenít meg. Ha SQLGetData SQLSTATE 01004-et jelez, ismeretlen hosszúságot vagy a puffernél nagyobb hosszúságot, az alkalmazás jelenti a problémát, és kilép anélkül, hogy részleges nevet nyomtatna ki.
Az alkalmazás létrehozása és futtatása
Ugyanabban a fejlesztői PowerShell ablakban fordítsd le az alkalmazást:
cl /std:c++17 /EHsc /W4 odbc-quickstart.cpp /link odbc32.libFuttassa az alkalmazást:
.\odbc-quickstart.exe
Az alkalmazás szabványos kimenete:
Product ID Name
---------- ----
680 HL Road Frame - Black, 58
706 HL Road Frame - Red, 58
707 Sport-100 Helmet, Red
708 Sport-100 Helmet, Black
709 Mountain Bike Socks, M
Töröld a kapcsolati karakterlánc-et, ha végeztél.