Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Important
SQL Server Native Client (SNAC) wordt niet geleverd met:
- SQL Server 2022 (16.x) en latere versies
- SQL Server Management Studio 19 en latere versies
De SQL Server Native Client (SQLNCLI of SQLNCLI11) en de verouderde Microsoft OLE DB-provider voor SQL Server (SQLOLEDB) worden niet aanbevolen voor de ontwikkeling van nieuwe toepassingen.
Gebruik een van de volgende stuurprogramma's voor nieuwe projecten:
Voor SQLNCLI die als onderdeel van SQL Server Database Engine (versies 2012 tot en met 2019) wordt geleverd, raadpleegt u deze uitzondering voor de levenscyclus van ondersteuning.
De SQL Server 2012 (11.x) Native Client ODBC Driver (SQLNCLI11.dll) veranderde de manier waarop hij SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) en SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX)) conversies doet. ODBC-functies, zoals SQLGetData, SQLBindCol, SQLBindParameter, geven (-4) SQL_NO_TOTAL als lengte/indicatorparameter terug wanneer de SQL Server Native Client ODBC-driver uit 2012 wordt gebruikt. Eerdere versies van de SQL Server Native Client ODBC-driver gaven een lengtewaarde terug, die onjuist kan zijn.
SQLGetData-gedrag
Veel Windows-functies laten je een buffergrootte van 0 specificeren en de teruggegeven lengte is de grootte van de teruggegeven data. Het volgende patroon is gebruikelijk voor Windows-programmeurs:
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 mag echter in dit scenario niet worden gebruikt. Het volgende patroon mag niet worden gebruikt:
// 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 alleen worden aangeroepen om stukken van de daadwerkelijke data op te halen. Het gebruik van SQLGetData om de grootte van de data te krijgen is niet onondersteund.
Het volgende toont het effect van de driverwissel wanneer je het verkeerde patroon gebruikt. Deze applicatie doet een query-query in een varchar-kolom en binding als Unicode (SQL_UNICODE/SQL_WCHAR):
Vraag: select convert(varchar(36), '123')
SQLGetData(hstmt, SQL_WCHAR, ....., (SQLPOINTER*) 0x1, 0 , &iSize); // Attempting to determine storage size needed
| SQL Server Native Client ODBC Driver-versie | Lengte of Indicator Uitkomst | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Native Client of eerder | 6 | De machinist ging er ten onrechte van uit dat het omzetten van CHAR naar WCHAR mogelijk was als lengte * 2. |
| SQL Server 2012 (11.x) Native Client (versie 11.0.2100.60) of later | -4 (SQL_NO_TOTAL) | De bestuurder gaat er niet langer van uit dat het omrekenen van CHAR naar WCHAR of WCHAR naar CHAR een (vermenigvuldigende) *2 of (delen)/2 actie is. Het aanroepen van SQLGetData geeft niet langer de lengte van de verwachte conversie terug. De bestuurder detecteert de omzetting naar of van CHAR en WCHAR en geeft (-4) SQL_NO_TOTAL in plaats van *2 of /2 gedrag terug dat onjuist kan zijn. |
Gebruik SQLGetData om de stukken van de data op te halen. (Pseudocode getoond:)
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-gedrag
Vraag: 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 Driver-versie | Lengte of Indicator Uitkomst | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Native Client of eerder | 20 |
SQLFetch meldt dat er een afkap is aan de rechterkant van de data. Lengte is de lengte van de teruggegeven gegevens, niet wat er is opgeslagen (gaat ervan uit dat *2 CHAR-naar-WCHAR-conversie is, wat voor glyphs onjuist kan zijn). De gegevens die in de buffer zijn opgeslagen zijn 123/0. Buffer is gegarandeerd NULL beëindigd. |
| SQL Server 2012 (11.x) Native Client (versie 11.0.2100.60) of later | -4 (SQL_NO_TOTAL) |
SQLFetch meldt dat er een afkap is aan de rechterkant van de data. Lengte geeft -4 (SQL_NO_TOTAL) aan omdat de rest van de data niet is omgezet. De gegevens die in de buffer worden opgeslagen zijn 123/0. - De buffer wordt gegarandeerd NULL beëindigd. |
SQLBindParameter (OUTPUT Parameter Gedrag)
Vraag: 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 Driver-versie | Lengte of Indicator Uitkomst | Description |
|---|---|---|
| SQL Server 2008 R2 (10.50.x) Native Client of eerder | 2468 |
SQLFetch levert geen beschikbare data meer. SQLMoreResults levert geen beschikbare data meer. Lengte geeft de grootte aan van de data die door de server wordt teruggestuurd, niet opgeslagen in de buffer. De originele buffer bevat 63 bytes en een NULL-terminator. Buffer is gegarandeerd NULL beëindigd. |
| SQL Server 2012 (11.x) Native Client (versie 11.0.2100.60) of later | -4 (SQL_NO_TOTAL) |
SQLFetch levert geen beschikbare data meer. SQLMoreResults levert geen beschikbare data meer. Lengte geeft aan (-4) SQL_NO_TOTAL omdat de rest van de data niet is omgezet. De originele buffer bevat 63 bytes en een NULL-terminator. Buffer is gegarandeerd NULL beëindigd. |
Het uitvoeren van CHAR- en WCHAR-conversies
De SQL Server 2012 (11.x) Native Client ODBC-driver biedt verschillende manieren om CHAR- en WCHAR-conversies uit te voeren. De logica lijkt op het manipuleren van blobs (varchar(max), nvarchar(max), ...):
Data wordt opgeslagen of afgekapt in de opgegeven buffer wanneer je bindt met SQLBindCol of SQLBindParameter.
Als je niet bindt, kun je de data in chunks ophalen door SQLGetData en SQLParamData te gebruiken.