クライアント コード ページがサーバー コード ページと異なる場合、SQL Server ODBC ドライバーを使用してクライアントからサーバーに文字データを正しく変換できない

この記事では、SQL Server ODBC ドライバーを使用するときにクライアント データの変換が正しくない問題を回避するのに役立ちます。

元の製品バージョン: SQL Server
元の KB 番号: 234748

現象

MDAC 2.1 以降のバージョンの SQL Server ODBC ドライバー (バージョン 3.70.0623 以降) または OLEDB プロバイダー (バージョン 7.01.0623 以降) を使用する場合、場合によっては、接続に対して Autotranslation が無効になっている場合でも、クライアント コード ページからサーバー コード ページへの文字データの変換が発生することがあります。

原因

Autotranslation は、コード ページの変換につながる唯一のメカニズムではありません。 SQL Server 7.0 ODBC ドライバーと OLEDB プロバイダーは、MSDE 1.0、SQL Server 7.0、またはそれ以降のバージョンのいずれかに接続するときに新しい動作を導入します。 言語イベントとして送信されるすべての SQL ステートメントは、サーバーに送信される前にクライアントの Unicode に変換されます。 終了効果は、接続の現在のAutotranslation設定に関係なく、言語イベントを介してクライアントからサーバーに送信されるすべてのデータのAutotranslationに似ています。 SQL Server のコード ページ以外のコード ページから翻訳されていない文字データを格納しようとする場合を除き、問題は発生しません。

回避策

コード ページ X データをコード ページ Y SQL Server に格納しないでください (たとえば、コード ページ 950 データはコード ページ 1252 サーバーに格納します)。 これは、以前のバージョンの SQL Server では状況によっては可能でしたが、常にサポートされていませんでした。 1252 SQL Server では、1252 文字以外の文字データは無効です。 別のコード ページの Unicode 以外の文字データは正しく並べ替えされず、デュアルバイト (DBCS) データの場合、SQL Server は文字境界を正しく認識しません。 重大な問題が発生する可能性があります。

SQL Server のコード ページに最適な選択肢は、サーバーにアクセスするクライアントのコード ページです。

サーバーとクライアントのコード ページは異なる場合がありますが、すべてのケースでサーバーのコード ページとの間でデータを適切に変換できるように、クライアントで自動変換が有効になっていることを確認する必要があります。

サーバーで複数のコード ページのデータを格納する必要がある場合、サポートされている解決策は、Unicode 列 (NCHAR/NVARCHAR/NTEXT) にデータを格納することです。

コード ページ X のデータをコード ページ Y SQL Server に格納する必要がある場合、これを確実に行うには次の 2 つの方法しかありません。

  • データをバイナリ列 (BINARY/VARBINARY/IMAGE) 列に格納します。
  • 文字データを処理するすべての SQL ステートメントにリモート プロシージャ コール (RPC) を使用するようにアプリケーションを記述します。 RPC イベントを介して送信されたデータは、変換の対象になりません。 ドライバーまたは DSN レベルでは、送信されるイベントの種類を変更するために実行できる操作はありません。 コマンドが言語または RPC イベントとして送信されるかどうかは、アプリケーションの記述時にプログラマが選択した API と構文によって完全に異なります。

詳細

自動変換 (つまり、新しい ODBC アプリケーションの 文字データの変換 チェック ボックス) は、変換メディアとして Unicode を使用して、データをサーバーに送信する前に、クライアント コード ページからサーバー コード ページに文字データを変換します。 ただし、3.7 SQL Server ODBC ドライバーは、言語イベントとして送信されたすべての SQL ステートメントを Unicode に変換してからネットワークに配置します。これは、自動変換に似ていますが、自動変換設定では制御されません。 これに対し、サーバーからクライアントに戻る文字データは、自動変換フラグを尊重します。自動変換がオフになっている場合、データは、サーバー上のデータと同じ文字コードを使用してクライアント アプリケーションに到着します。 同様に、クライアントからサーバーへの RPC イベントのデータ変換は、自動変換をオフにすることで無効にすることができます。 動作が言語イベントに与える影響を示す単純なスクリプトが続きます。 この例は、コード ページ 437 サーバーに接続しているコード ページ 1252 クライアントで Query Analyzer から実行されました。

-- Turn Autotranslation off here.
 USE tempdb
 GO
 CREATE TABLE t1 (c1 int, c2 char(1))
 GO

-- Enter a yen character, using the keystroke ALT-0165.
 INSERT INTO t1 VALUES (1, '¥') 
 SELECT c1, c2, ASCII (c2) FROM t1
c1 c2 
 ----------- ---- ----------- 
 1  157

(1 row(s) affected)

前の例について次に示します。

  • このバッチ中に Autotranslation がオフであったにもかかわらず、文字コード 165 (コード ページ 1252 の円) は 157 (コード ページ 437 では円) に変換されました。 これは、ODBC ドライバーがサーバーを送信する前に SQL 文字列を Unicode に変換したため、サーバーがコード ページ 437 のストレージに適した文字に変換できたためです。
  • クライアントが SELECT を実行して保存されたデータを取得すると、文字 157 はクライアントに翻訳されていません (157 はコード ページ 1252 クライアントのボックス '' として表示されます)。 これは、この記事で説明する変換は、サーバーからクライアントにではなく、クライアントからサーバーに送信されたデータにのみ適用されるためです。 Autotranslation設定がオフになっているため、データは変換されませんでした。
-- Turn Autotranslation back on before running the following batch.
 INSERT INTO t1 VALUES (2, '¥')
 SELECT c1, c2, ASCII (c2) FROM t1
c1 c2 
 ----------- ---- ----------- 
 1 ¥ 157
 2 ¥ 157

(2 row(s) affected)

この場合、 Autotranslation をオンに戻しても、クライアントからサーバーへの変換には影響しませんでした (つまり、文字コード 165 から文字コード 157 への変換は同じです)、サーバーから取得されたデータに影響を与えました。 今回 SELECT ステートメントを実行すると ( Autotranslation をオンにして)、円記号がコード ページ 1252 アプリケーションに正しく表示されます。これは、 Autotranslation メカニズムによって文字コード 157 から文字コード 165 に変換されているためです。

SQL Server ODBC ドライバー バージョン 3.70 以降を使用し、SQL Server 7.0 以降に接続すると、この動作 (クライアントでの言語イベントから Unicode への変換) が表示されます。 以前の ODBC ドライバーを使用している場合、または 3.7 ドライバーを使用して SQL Server 6.5 以前に接続する場合は発生しません。 さらに、Unicode 列 (NCHAR/NVARCHAR/NTEXT) にデータを格納する場合、変換は問題になりません。

SQL Server 2005 での文字データの表現方法の詳細については、「 Character データは、クライアント コンピューターのコード ページが SQL Server 2005 のデータベースのコード ページと異なる場合に正しく表されないを参照してください。