文字変換処理での ODBC ドライバーの動作の変更ODBC Driver Behavior Change When Handling Character Conversions

適用対象: yesSQL Server yesAzure SQL Database yesAzure Synapse Analytics (SQL DW) yesParallel Data Warehouse APPLIES TO: yesSQL Server yesAzure SQL Database yesAzure Synapse Analytics (SQL DW) yesParallel Data Warehouse

Native SQL Server 2012 (11.x)SQL Server 2012 (11.x) Client ODBC ドライバー (SQLNCLI11) では、SQL_WCHAR * (NCHAR/NVARCHAR/NVARCHAR (max)) と SQL_CHAR* (CHAR/VARCHAR/NARCHAR (max)) 変換の動作が変更されました。The SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client ODBC Driver (SQLNCLI11.dll) changed how it does of SQL_WCHAR* (NCHAR/NVARCHAR/NVARCHAR(MAX)) and SQL_CHAR* (CHAR/VARCHAR/NARCHAR(MAX)) conversions. SQL ServerSQL Server 2012 Native Client ODBC ドライバーを使用する場合、SQLGetData、SQLBindCol、SQLBindParameter などの ODBC 関数では長さまたはインジケーターのパラメーターとして (-4) SQL_NO_TOTAL が返されます。ODBC functions, such as SQLGetData, SQLBindCol, SQLBindParameter, return (-4) SQL_NO_TOTAL as the length/indicator parameter when using the SQL ServerSQL Server 2012 Native Client ODBC driver. 以前のバージョンの SQL ServerSQL Server Native Client ODBC ドライバーでは長さの値が返されましたが、これは誤りである可能性があります。Prior versions of the SQL ServerSQL Server Native Client ODBC driver returned a length value, which can be incorrect.

SQLGetData の動作SQLGetData Behavior

多くの Windows 関数ではバッファー サイズに 0 を指定できます。返される長さは、返されるデータのサイズです。Many Windows functions let you specify a buffer size of 0 and the returned length is the size of the returned data. 以下は、Windows プログラミングで一般的なパターンです。The following pattern is common for Windows programmers:

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を使用しないでください。However, SQLGetData should not be used in this scenario. 次のパターンは使用できません。The following pattern should not be used:

// 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は、実際のデータのチャンクを取得するためにのみ呼び出すことができます。SQLGetData can only be called to retrieve chunks of actual data. SQLGetDataを使用してデータのサイズを取得することはサポートされていません。Using SQLGetData to get the size of data is not unsupported.

次に、不適切なパターンを使用した場合のドライバーの変更による影響を示します。The following shows the impact of the driver change when you use the incorrect pattern. このアプリケーションは、 varchar型の列とバインドを Unicode (SQL_UNICODE/SQL_WCHAR) としてクエリを実行します。This application queries a varchar column and binding as Unicode (SQL_UNICODE/SQL_WCHAR):

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

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

| SQL ServerSQL Server Native Client ODBC ドライバーのバージョンSQL ServerSQL Server Native Client ODBC Driver version|長さまたはインジケーターの結果Length or Indicator Outcome|[説明]Description|
|-----------------------------------------------------------------|---------------------------------|-----------------|
| SQL Server 2008 R2SQL Server 2008 R2 Native Client 以前SQL Server 2008 R2SQL Server 2008 R2 Native Client or earlier|66|ドライバーには、CHAR から WCHAR への変換が長さ * 2 として実行できるという誤った想定がありました。The driver incorrectly assumed that converting CHAR to WCHAR could be accomplished as length * 2.|
| SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (Version 11.0.2100.60) 以降SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) or later|-4 (SQL_NO_TOTAL)-4 (SQL_NO_TOTAL)|ドライバーは、CHAR から WCHAR または WCHAR から CHAR への変換が、(乗算) *2 または (除算)/2 アクションであると想定しなくなりました。The driver no longer assumes that converting from CHAR to WCHAR or WCHAR to CHAR is a (multiply) *2 or (divide)/2 action.

SQLGetDataを呼び出すと、予期される変換の長さが返されなくなりました。Calling SQLGetData no longer returns the length of the expected conversion. ドライバーでは CHAR と WCHAR との間の変換が検出され、誤りの可能性のある *2 または /2 の動作の代わりに (-4) SQL_NO_TOTAL が返されます。The driver detects the conversion to or from CHAR and WCHAR and returns (-4) SQL_NO_TOTAL instead of *2 or /2 behavior that could be incorrect.|

SQLGetDataを使用して、データのチャンクを取得します。Use SQLGetData to retrieve the chunks of the data. (擬似コードを示します)。(Pseudo code shown:)

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

SQLBindCol の動作SQLBindCol Behavior

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

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

| SQL ServerSQL Server Native Client ODBC ドライバーのバージョンSQL ServerSQL Server Native Client ODBC Driver version|長さまたはインジケーターの結果Length or Indicator Outcome|[説明]Description|
|-----------------------------------------------------------------|---------------------------------|-----------------|
| SQL Server 2008 R2SQL Server 2008 R2 Native Client 以前SQL Server 2008 R2SQL Server 2008 R2 Native Client or earlier|2020|Sqlfetchは、データの右側に切り捨てがあることを報告します。SQLFetch reports that there is a truncation on the right side of the data.

長さは格納されたデータではなく、返されるデータの長さです (*2 による CHAR から WCHAR への変換が想定されていますが、グリフでは誤りである可能性があります)。Length is the length of the data returned, not what was stored (assumes *2 CHAR to WCHAR conversion which can be incorrect for glyphs).

バッファーに格納されているデータは 123 \ 0 です。Data stored in buffer is 123\0. バッファーは NULL 終端であることが保証されます。Buffer is guaranteed to be NULL terminated.|
| SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (Version 11.0.2100.60) 以降SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) or later|-4 (SQL_NO_TOTAL)-4 (SQL_NO_TOTAL)|Sqlfetchは、データの右側に切り捨てがあることを報告します。SQLFetch reports that there is a truncation on the right side of the data.

残りのデータは変換されていないため、長さは -4 (SQL_NO_TOTAL) を示します。Length indicates -4 (SQL_NO_TOTAL) because the rest of the data was not converted.

バッファーに格納されているデータは 123\0 です。Data stored in the buffer is 123\0. - バッファーは NULL 終端であることが保証されます。- Buffer is guaranteed to be NULL terminated.|

SQLBindParameter (出力パラメーターの動作)SQLBindParameter (OUTPUT Parameter Behavior)

照会create procedure spTest @p1 varchar(max) OUTPUTQuery: create procedure spTest @p1 varchar(max) OUTPUT

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

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

| SQL ServerSQL Server Native Client ODBC ドライバーのバージョンSQL ServerSQL Server Native Client ODBC Driver version|長さまたはインジケーターの結果Length or Indicator Outcome|[説明]Description|
|-----------------------------------------------------------------|---------------------------------|-----------------|
| SQL Server 2008 R2SQL Server 2008 R2 Native Client 以前SQL Server 2008 R2SQL Server 2008 R2 Native Client or earlier|24682468|Sqlfetchは、使用可能なデータがないことを返します。SQLFetch returns no more data available.

Sqlmoreresultsは、これ以上使用できるデータを返しません。SQLMoreResults returns no more data available.

長さはバッファーに格納されたデータではなく、サーバーから返されるデータのサイズを示します。Length indicates the size of the data returned from server, not stored in buffer.

元のバッファーには 63 バイトと NULL ターミネータが含まれます。Original buffer contains 63 bytes and a NULL terminator. バッファーは NULL 終端であることが保証されます。Buffer is guaranteed to be NULL terminated.|
| SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (Version 11.0.2100.60) 以降SQL Server 2012 (11.x)SQL Server 2012 (11.x) Native Client (version 11.0.2100.60) or later|-4 (SQL_NO_TOTAL)-4 (SQL_NO_TOTAL)|Sqlfetchは、使用可能なデータがないことを返します。SQLFetch returns no more data available.

Sqlmoreresultsは、これ以上使用できるデータを返しません。SQLMoreResults returns no more data available.

残りのデータは変換されていないため、長さは (-4) SQL_NO_TOTAL を示します。Length indicates (-4) SQL_NO_TOTAL because the rest of the data was not converted.

元のバッファーには 63 バイトと NULL ターミネータが含まれます。Original buffer contains 63 bytes and a NULL terminator. バッファーは NULL 終端であることが保証されます。Buffer is guaranteed to be NULL terminated.|

CHAR と WCHAR の変換の実行Performing CHAR and WCHAR Conversions

[!INCLUDE[ssSQL11](../../../includes/sssql11-md.md)] Native Client ODBC ドライバーには、CHAR と WCHAR の変換を実行する方法が複数用意されています。The [!INCLUDE[ssSQL11](../../../includes/sssql11-md.md)] Native Client ODBC driver offers several ways to perform CHAR and WCHAR conversions. ロジックは、blob の操作 (varchar (max)、nvarchar (max)、...) に似ています。The logic is similar to manipulating blobs (varchar(max), nvarchar(max), ...): - **SQLBindCol**または**SQLBindParameter**にバインドする場合、データは指定されたバッファーに保存されるか、または切り捨てられます。Data is saved or truncated into the specified buffer when binding with **SQLBindCol** or **SQLBindParameter**. - バインドしない場合は、 **SQLGetData**と**sqlparamdata**を使用して、データをチャンク単位で取得できます。If you do not bind, you can retrieve the data in chunks by using **SQLGetData** and **SQLParamData**. ## 参照See Also [SQL Server Native Client の機能SQL Server Native Client Features](../../../relational-databases/native-client/features/sql-server-native-client-features.md)