web-dev-qa-db-ja.com

ファイルからインポートされた特殊文字を表示しない

このシナリオはSQL Serverインスタンスであり、主にBULK INSERT操作を使用してデータをフィードするデータベースです。スペイン語環境で作業しているため、挿入されたテキストの一部にñなどの特殊文字が含まれています。

したがって、最初の小さなテストの後、単純なselectを実行すると、これらの特殊文字が正しく表示されないことがわかりました。そのため、考えられるすべてのことを確認し始めます。

  • ファイルのエンコード:一括挿入されるファイルのエンコードは適切です:ANSI
  • データベースのエンコード:データベースのエンコードは適切です(ありがとうございます):select collation_name from sys.databases where name='DBNAME';結果はSQL_Latin1_General_CP1_CI_AS になります。
    • Latin1:使用される文字セット。これは私に十分合っています
    • 一般:ここで特に興味深いことはありません
    • CP1:これは、コードページ1を使用することを意味します。つまり、コードページ1252 <=>は、Latin1とかなり類似したWIN-1252のエンコードに使用されます。
    • CI:大文字と小文字を区別しません
    • AS:アクセント記号が区別されるため、áは
  • データをファイルにエクスポートしてチェック:ファイルのエンコーディングはANSI butデータは正しく表示されません。特殊文字はありません。代わりに、テキストを読みにくくする他の文字がいくつか見つかります。

これらのテストで、データ正しく保存されていないであると結論付けました。これが、データが正しく表示およびエクスポートされない理由です。インターネットで見つけたほとんどすべての解決策は、文字列データ型フィールドにnvarcharではなくvarcharを使用することを提案していますが、それでもこのシナリオは解決されません。私の挿入を妨害しているのは何ですか?

3
Feillen

文字が正しくインポートされていない場合、これは実際には2段階のプロセスであるため、次の領域の1つ(または両方)に問題があります。

  1. BCP/BULK INSERTはファイルがどのようにエンコードされているかを認識しておらず、誤って解釈しています

  2. 宛先列はVARCHAR(またはCHAR {or TEXT、ただしTEXT}は使用しないでください)およびその宛先の照合column(データベースではない)は、誤ってインポートされた文字のマッピングがないコードページを使用します。

ここで、インポートテーブルが存在するデータベースのデフォルトの照合順序は関係がないことに注意してください。ここで重要な唯一の照合順序は、インポートされる特定の各文字列列の照合順序です。また、すべての文字列列の照合順序は異なる場合があり、それらのいずれもデータベースのデフォルトの照合順序と同じである必要はありません。データベース内のほとんどの列の照合順序をデータベースのデフォルトと一致させるのは一般的です。これは、新しいテーブルと列を作成するときに使用され、COLLATEキーワードを介して照合順序を指定しないためです。

ステップ1:ファイルのエンコード
BCP/BULK INSERT(またはファイルを読み取る他のほとんどのコード)は、ファイルがいくつかのエンコーディングの1つを使用して Byte Order Mark(BOM ) 。ただし、拡張ASCIIエンコーディングはバイトオーダーマークを使用しないため、少なくとも確実にプログラムで決定することはできません。拡張ASCIIエンコーディングを使用すると、コードページを指定する必要があるか、デフォルトが想定されます。

bcp Utility のMSDNページに従って、-Cオプションの下:

OEM->クライアントが使用するデフォルトのコードページ。これは、-Cが指定されていない場合に使用されるデフォルトのコードページです。

コマンドプロンプトを開いてmodeまたはchcpを実行すると、デフォルトのコードページを確認できます(chcpを使用すると、コードページを変更することもできます。価値)。

デフォルトのコードページが850で、ファイルがWindows-1252 Latin1(ANSI)のエンコーディングで保存されている場合、2つのコードページ間で文字マッピングが同じではないため、ファイルの解釈に問題が発生する可能性があります。これは、SQL Serverとはまったく関係ありません。

コードページ1252では、ñ文字の値は241です。ただし、コードページ850では、同じ文字の値は164です。ファイルは、他のものに関係なく、一連のバイトであり、それらの1つです。 bytesの10進数値は241です(保存時に、ñを241として格納する必要があると判断したコードページ1252を使用するように指示されたため)。これで、BCPがファイルを読み取るときに、デフォルトのMS-DOSコードページ850を使用している場合、同じバイト値241が文字±にマップされます。 1252スイッチを介してACPまたは-C(同じもの)のコードページを指定すると、BCPは値241のバイトが実際にはñ。または、1255(Windowsヘブライ語)のコードページを指定すると、BCP/BULK INSERTは241の同じバイト値を文字סとして解釈します。

ステップ2:宛先列のデータ型と照合順序

BCP/BULK INSERT(または任意のクライアントアプリ)がデータを読み込むと、ベースバイト値だけでなく、それらのマッピングとして存在します。 BCP/BULK INSERTに読み込まれた文字は、宛先のデータ型と照合順序でマップできる限り、宛先列その文字としてに格納されます。宛先データ型NVARCHARNCHAR、およびNTEXT(ただしNTEXTは使用しない)は、すべての文字を保持できるため、何でもかまいません照合はです。ただし、コピー先のデータ型がVARCHARCHAR、またはTEXTの場合、照合はコードページを決定し、次にコードページが文字マッピングを決定します。宛先データ型が最後に言及した3つのうちの1つである場合andは、ファイルに使用されたのと同じコードページに関連付けられた照合を使用し、すべてが正常に機能するはずです。または、照合が別のコードページに関連付けられている場合、バイト値ではなく文字をマップしようとします。

つまり、BCP/BULK INSERTがコードページ1252および文字ñ(コードページ1252の値241)で機能している場合、照合でVARCHAR列にインポートするとof SQL_Latin1_General_CP850_CI_AS-これはコードページ850を使用します-次に、ñの代わりに±(同じ文字ですが、コードページ850の値は164)の文字が表示されます。コードページ850の同じ241値。ただし、Hebrew_CI_ASの照合順序を持つVARCHAR列にインポートすると、コードページ1255を使用しますが、代わりに?が表示されます。コードページ1255のסのマッピングがないため、ñ(コードページ1255の値241)。

4
Solomon Rutzky

私と同じような問題が発生する可能性のある人にとって、私のために働いたのはコードページシステムに関連したものでした。さらに詳しく説明します。

データベースの照合では、データベースがコードページ1252を使用し、コンピューターのアクティブなコードページをチェックした後(cmdを実行し、次にcmd内でmode)、850であることがわかりました。紛争が起こっていたに違いありません!
コンピューターが私の特殊文字を正しく印刷できない場合、データベースは私のコンピューターがそれに出力する愚かな文字列を保存します。

オプションCODEPAGE=ACPを追加しました。これにより、一括挿入がSQLサーバーのコードページを使用するように強制され、すべてがうまくいきました:)

2
Feillen