Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
gäller för:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Viktigt!
SQL Server Native Client (SNAC) levereras inte med:
- SQL Server 2022 (16.x) och senare versioner
- SQL Server Management Studio 19 och senare versioner
SQL Server Native Client (SQLNCLI eller SQLNCLI11) och den äldre Microsoft OLE DB-providern för SQL Server (SQLOLEDB) rekommenderas inte för ny programutveckling.
Använd någon av följande drivrutiner för nya projekt:
För SQLNCLI som levereras som en komponent i SQL Server-databasmotorn (versioner 2012 till och med 2019), se det här Support Lifecycle-undantag.
Den SQL Server 2012 (11.x) Native Client ODBC Driver (SQLNCLI11.dll) ändrade hur den gör SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) och SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX))-konverteringar. ODBC-funktioner, såsom SQLGetData, SQLBindCol, SQLBindParameter, returnerar (-4) SQL_NO_TOTAL som längd/indikatorparameter när man använder SQL Server 2012 Native Client ODBC-drivrutin. Tidigare versioner av SQL Server Native Client ODBC-drivrutinen returnerade ett längdvärde, vilket kan vara felaktigt.
SQLGetData-beteende
Många Windows-funktioner låter dig ange en buffertstorlek på 0 och den returnerade längden är storleken på den returnerade datan. Följande mönster är vanligt bland Windows-programmerare:
int iSize = 0;
BYTE * pBuffer = NULL;
GetMyFavoriteAPI(pBuffer, &iSize); // Returns needed size in iSize
pBuffer = new BYTE[iSize]; // Allocate buffer
GetMyFavoriteAPI(pBuffer, &iSize); // Retrieve actual data
SQLGetData bör dock inte användas i detta scenario. Följande mönster bör inte användas:
// bad
int iSize = 0;
WCHAR * pBuffer = NULL;
SQLGetData(hstmt, SQL_W_CHAR, ...., (SQLPOINTER*)0x1, 0, &iSize); // Get storage size needed
pBuffer = new WCHAR[(iSize/sizeof(WCHAR)) + 1]; // Allocate buffer
SQLGetData(hstmt, SQL_W_CHAR, ...., (SQLPOINTER*)pBuffer, iSize, &iSize); // Retrieve data
SQLGetData kan endast anropas för att hämta bitar av faktisk data. Att använda SQLGetData för att få datastorleken är inte utan stöd.
Följande visar effekten av driverbytet när du använder fel mönster. Denna applikation frågar en varchar-kolumn och bindning som Unicode (SQL_UNICODE/SQL_WCHAR):
Fråga: select convert(varchar(36), '123')
SQLGetData(hstmt, SQL_WCHAR, ....., (SQLPOINTER*) 0x1, 0 , &iSize); // Attempting to determine storage size needed
| SQL Server Native Client ODBC-drivrutinsversion | Längd eller indikatorresultat | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Inbyggd klient eller tidigare | 6 | Föraren antog felaktigt att konvertering av CHAR till WCHAR kunde göras som längd * 2. |
| SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) eller senare | -4 (SQL_NO_TOTAL) | Föraren antar inte längre att konvertering från CHAR till WCHAR eller WCHAR till CHAR är en (multiplicera) *2 eller (dividera)/2-åtgärd. Att anropa SQLGetData returnerar inte längre längden på den förväntade konverteringen. Föraren känner av omvandlingen till eller från CHAR och WCHAR och returnerar (-4) SQL_NO_TOTAL istället för *2 eller /2 beteende som kan vara felaktigt. |
Använd SQLGetData för att hämta databitarna. (Pseudokod visas:)
while( (SQL_SUCCESS or SQL_SUCCESS_WITH_INFO) == SQLFetch(...) ) {
SQLNumCols(...iTotalCols...)
for(int iCol = 1; iCol < iTotalCols; iCol++) {
WCHAR* pBufOrig, pBuffer = new WCHAR[100];
SQLGetData(.... iCol ... pBuffer, 100, &iSize); // Get original chunk
while(NOT ALL DATA RETRIEVED (SQL_NO_TOTAL, ...) ) {
pBuffer += 50; // Advance buffer for data retrieved
// May need to realloc the buffer when you reach current size
SQLGetData(.... iCol ... pBuffer, 100, &iSize); // Get next chunk
}
}
}
SQLBindCol-beteende
Fråga: select convert(varchar(36), '1234567890')
SQLBindCol(... SQL_W_CHAR, ...) // Only bound a buffer of WCHAR[4] - Expecting String Data Right Truncation behavior
| SQL Server Native Client ODBC-drivrutinsversion | Längd eller indikatorresultat | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Inbyggd klient eller tidigare | 20 |
SQLFetch rapporterar att det finns en trunkering på höger sida av datan. Längd är längden på den data som returneras, inte vad som lagrades (antar *2 CHAR till WCHAR-konvertering vilket kan vara felaktigt för glyfer). Data lagrad i buffert är 123/0. Buffern garanteras vara NULL-terminerad. |
| SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) eller senare | -4 (SQL_NO_TOTAL) |
SQLFetch rapporterar att det finns en trunkering på höger sida av datan. Längd indikerar -4 (SQL_NO_TOTAL) eftersom resten av datan inte konverterades. Data som lagras i bufferten är 123/0. - Bufferten garanteras vara NULL-terminerad. |
SQLBindParameter (OUTPUT-parameterbeteende)
Fråga: create procedure spTest @p1 varchar(max) OUTPUT
select @p1 = replicate('B', 1234)
SQLBindParameter(... SQL_W_CHAR, ...) // Only bind up to first 64 characters
| SQL Server Native Client ODBC-drivrutinsversion | Längd eller indikatorresultat | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Inbyggd klient eller tidigare | 2468 |
SQLFetch returnerar ingen mer tillgänglig data. SQLMoreResults returnerar ingen mer tillgänglig data. Längd anger storleken på data som returneras från servern, inte lagrad i bufferten. Den ursprungliga bufferten innehåller 63 byte och en NULL-terminator. Buffern garanteras vara NULL-terminerad. |
| SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) eller senare | -4 (SQL_NO_TOTAL) |
SQLFetch returnerar ingen mer tillgänglig data. SQLMoreResults returnerar ingen mer tillgänglig data. Längd indikerar (-4) SQL_NO_TOTAL eftersom resten av datan inte konverterades. Den ursprungliga bufferten innehåller 63 byte och en NULL-terminator. Buffern garanteras vara NULL-terminerad. |
Utförande av CHAR- och WHAR-konverteringar
SQL Server 2012 (11.x) Native Client ODBC-drivrutinen erbjuder flera sätt att utföra CHAR- och WCHAR-konverteringar. Logiken liknar att manipulera blobs (varchar(max), nvarchar(max), ...):
Data sparas eller trunkeras in i den angivna bufferten när man binder med SQLBindCol eller SQLBindParameter.
Om du inte binder kan du hämta data i chunkar genom att använda SQLGetData och SQLParamData.