Condividi tramite


Modifica del comportamento del driver ODBC quando si gestiscono le conversioni di caratteri

Nel driver ODBC di SQL Server 2012 Native Client (SQLNCLI11.dll) è stata modificata la modalità di esecuzione delle conversioni SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) e SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX)). Tramite le funzioni ODBC, ad esempio SQLGetData, SQLBindCol, SQLBindParameter viene restituito (-4) SQL_NO_TOTAL come parametro di lunghezza/indicatore quando si utilizza il driver ODBC di SQL Server 2012 Native Client. Dalle versioni precedenti del driver ODBC di SQL Server Native Client viene restituito un valore di lunghezza che può essere errato.

Comportamento di SQLGetData

Tramite le numerose funzioni di Windows è possibile specificare dimensioni del buffer pari a 0 e la lunghezza restituita corrisponde alle dimensioni dei dati restituiti. Di seguito è riportato un modello comune per i programmatori di Windows:

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

Tuttavia, la funzione SQLGetData non deve essere utilizzata in questo scenario. Non è consigliabile utilizzare il modello seguente:

// 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

La funzione SQLGetData può essere chiamata solo per recuperare blocchi di dati effettivi. L'utilizzo della funzione SQLGetData per ottenere le dimensioni dei dati non è supportato.

Di seguito viene illustrato l'impatto della modifica del driver quando si utilizza il modello errato. Tramite questa applicazione viene eseguita una query su una colonna varchar e su un'associazione come Unicode (SQL_UNICODE/SQL_WCHAR):

Query: select convert(varchar(36), '123')

SQLGetData(hstmt, SQL_WCHAR, ….., (SQLPOINTER*) 0x1, 0 , &iSize);   // Attempting to determine storage size needed

Versione del driver ODBC di SQL Server Native Client

Risultato della lunghezza o dell'indicatore

Descrizione

SQL Server 2008 R2 Native Client o versioni precedenti

6

È stato erroneamente presupposto dal driver che la conversione di CHAR in WCHAR potesse essere effettuata come lunghezza * 2.

SQL Server 2012 Native Client (versione 11.0.2100.60) o successive

-4 (SQL_NO_TOTAL)

Tramite il driver non viene più presupposto che la conversione da CHAR a WCHAR o da WCHAR a CHAR sia un'azione di (moltiplicazione) *2 o (divisione)/2.

Tramite la chiamata alla funzione SQLGetData non viene più restituita la lunghezza della conversione prevista. Tramite il driver viene rilevata la conversione a o da CHAR e WCHAR e viene restituito (-4) SQL_NO_TOTAL anziché il comportamento *2 o /2 che potrebbe essere errato.

Utilizzare la funzione SQLGetData per recuperare i blocchi di dati (di seguito è riportato uno pseudocodice):

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 RETREIVED (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
      }
   }
}

Comportamento di SQLBindCol

Query: select convert(varchar(36), '1234567890')

SQLBindCol(… SQL_W_CHAR, …)   // Only bound a buffer of WCHAR[4] – Expecting String Data Right Truncation behavior

Versione del driver ODBC di SQL Server Native Client

Risultato della lunghezza o dell'indicatore

Descrizione

SQL Server 2008 R2 Native Client o versioni precedenti

20

  • Tramite SQLFetch viene segnalata la presenza di un troncamento a destra dei dati.

  • La lunghezza corrisponde a quella dei dati restituiti e non di quelli archiviati (viene presupposta una conversione *2 CHAR a WCHAR che potrebbe essere errata per i glifi).

  • I dati archiviati nel buffer sono 123\0. Viene garantito che la terminazione del buffer sia NULL.

SQL Server 2012 Native Client (versione 11.0.2100.60) o successive

-4 (SQL_NO_TOTAL)

  • Tramite SQLFetch viene segnalata la presenza di un troncamento a destra dei dati.

  • Tramite la lunghezza viene indicato -4 (SQL_NO_TOTAL) poiché il resto dei dati non è stato convertito.

  • I dati archiviati nel buffer sono 123\0. - Viene garantito che la terminazione del buffer sia NULL.

SQLBindParameter (comportamento del parametro OUTPUT)

Query: create procedure spTest @p1 varchar(max) OUTPUT

select @p1 = replicate('B', 1234)

SQLBindParameter(… SQL_W_CHAR, …)   // Only bind up to first 64 characters

Versione del driver ODBC di SQL Server Native Client

Risultato della lunghezza o dell'indicatore

Descrizione

SQL Server 2008 R2 Native Client o versioni precedenti

2468

  • Tramite SQLFetch non viene restituito più alcun dato disponibile.

  • Tramite SQLMoreResults non viene restituito più alcun dato disponibile.

  • Tramite la lunghezza vengono indicate le dimensioni dei dati restituiti dal server e non di quelli archiviati nel buffer.

  • Nel buffer originale sono contenuti 63 byte e un carattere di terminazione NULL. Viene garantito che la terminazione del buffer sia NULL.

SQL Server 2012 Native Client (versione 11.0.2100.60) o successive

-4 (SQL_NO_TOTAL)

  • Tramite SQLFetch non viene restituito più alcun dato disponibile.

  • Tramite SQLMoreResults non viene restituito più alcun dato disponibile.

  • Tramite la lunghezza viene indicato (-4) SQL_NO_TOTAL poiché il resto dei dati non è stato convertito.

  • Nel buffer originale sono contenuti 63 byte e un carattere di terminazione NULL. Viene garantito che la terminazione del buffer sia NULL.

Esecuzione delle conversioni CHAR e WCHAR

Nel driver ODBC di SQL Server 2012 Native Client sono disponibili diverse modalità di esecuzione delle conversioni CHAR e WCHAR. La logica è simile alla modifica di BLOB (varchar(max), nvarchar(max), …):

  • I dati vengono salvati o troncati nel buffer specificato quando si esegue l'associazione con SQLBindCol o SQLBindParameter.

  • Se non viene eseguita l'associazione, è possibile recuperare i dati in blocchi utilizzando SQLGetData e SQLParamData.

Vedere anche

Altre risorse

Funzionalità di SQL Server Native Client