web-dev-qa-db-ja.com

Pythonで取得したSQL Server VARCHAR列のエンコードの問題

最近、SQL Serverでvarchar(120)として格納されているフィールドに関連するエンコーディングに問題がありました。 SSMSでは、varcharは次のように表示されます。

「ジョンベンを殺したのは誰?」

ただし、Pythonに取り込むと、次のように表示されます。

enter image description here

私はこれをPython側から調査しましたが、奇妙なことは何も起こっていません。私の理論では、SQL ServerのvarcharはpythonでSSMSとは異なる方法で表示されるUTF-8文字を受け入れます。 SQL Serverでのエンコードについてはあまり詳しくありません。誰かが私に次のことを知らせてくれますか?

  • SSMSでvarcharのエンコーディングを表示する方法はありますか?たとえば、現在SSMSからのコンマを表示する代わりに、\ x82を参照してください。
  • SQL Server 2008を使用しています。インポート/エクスポートツールを使用したり、フラットファイルにダンプしたりせずに、UTF-8文字のエンコードをASCII文字に変更する方法はありますか?つまりクエリでこの変換を行うことができますか?
  • クエリを介してプログラムで問題のあるレコードを特定する方法はありますか(問題は、ASCIIではサポートされていないUTF-8文字として定義されています)。

前もって感謝します!

sp_help N'table_name';を使用して、このVARCHAR列の照合順序はSQL_Latin1_General_CP1_CI_ASであることがわかりました。

10
Eric

SQL Serverは、いかなる状況でもUTF-8を格納しません。 NVARCHARNCHARおよびNTEXTを含むが、NTEXTを使用しない)およびXML、またはコードページに基づくVARCHARCHARおよびTEXTを含む)に基づく8ビットエンコーディングを使用して、UTF-16リトルエンディアン(LE)を取得します。 、ただしTEXTは使用しないでください)。

ここでの問題は、コードがその0x82文字を誤って変換し、UTF-8であると考えていることですが、そうではありません。 0x82の値を持つUTF-8「文字」はありません。これが、「不明」/「�」の置換記号を取得する理由です。シングルバイト0x82の文字がないことを示す次のUTF-8テーブルを参照してください。

TF-8エンコードテーブル

O.P.によって述べられているように、問題の列の照合順序はSQL_Latin1_General_CP1_CI_ASです。これは、8ビットエンコーディングがコードページ1252を使用していること、つまり Windows Latin 1(ANSI) であることを意味します。そして、そのチャート(文字名があるため、一番下のチャートまでスクロールします)の値0x82(「コードポイント」列で「82」を探します)を確認すると、実際には 単一の低い9の引用符 = SSMSに表示されます。その文字は、UTF-8では、3バイトのシーケンスです:E2 80 9A

Pythonコードは、SQL Server接続のクライアントエンコーディングをコードページ1252に設定する必要があるか、返された文字列のエンコーディングを変更/変換する必要があります。 fromコードページ1252toUTF-8。

もちろん、これがWebページに表示されている場合は、ページの宣言された文字セットをWindows-1252変更できますが、 UTF-8文字が既に存在する場合、ページ上の他の文字と干渉する可能性があります。

17
Solomon Rutzky