漢字を含むファイルをテーブルにインポートしようとしています。ファイルエンコーディングはBig5(Traditional)です。
以下は、インポートする必要があるようなサンプルファイルです。 https://www.pastiebin.com/5d7782d9b63fa
ファイルをインポートする必要があるテーブルには、次のような構造があります。
create table dbo.Test (
AccountId numeric(18, 0) not null
, Province nvarchar(50) null
, City nvarchar(50) collate Chinese_Hong_Kong_Stroke_90_CI_AI
, Country nvarchar(50) null
, Gender nvarchar(50) null
)
OPENROWSET/BULK
を使用してインポートすると、すべてのデータが正しく転送されます。
select AccountId, Province, City, Country, Gender
from openrowset (
bulk 'C:\chinese_sample.dat'
, firstrow = 1
, formatfile = 'C:\chinese_sample.xml'
) t
これが私が使用するフォーマットファイルです: https://www.pastiebin.com/5d7783396f9e4
しかし、SSISを使用してファイルをインポートしようとすると、中国語の文字が正しく解析されません。
フラットファイルソースでは、DataType文字列[DT_STR]とCodePage 950を使用します。次に、それをUnicode文字列[DT_WSTR]に変換します。
テキストがテーブルにインポートされる方法は次のとおりです。
ご覧のとおり、一部の文字は正しく解析され、一部の文字は正しく解析されていません。何が欠けていますか?
問題は、正しくインポートされていない行に、コードページ950でエンコードされ、末尾のバイトが0x7C
である文字が含まれていることです。これは有効ですbutは、たまたま区切り記号として使用しているパイプ記号でもあります。例えば:
SELECT CONVERT(VARBINARY(20), CONVERT(VARCHAR(20), N'四會'
COLLATE Chinese_Hong_Kong_Stroke_90_CI_AI));
-- 0xA57C B77C
これらの2つの文字のそれぞれの末尾バイトは0x7C
です。パーサーは、コードページ950文字の2バイトシーケンスの一部ではなく、区切り文字としてそれを表示しているようです。これが、「?」を取得する理由です。 「City」と「Country」の両方で、「Gender」列に残りの入力行があります。 「?」これらの2つの列の先頭のバイト0xA5
と0xB7
は、それ自体では有効でないためです。
次の行にも同じ問題があります。
SELECT CONVERT(VARBINARY(20), CONVERT(VARCHAR(20), N'元朗大坑|'
COLLATE Chinese_Hong_Kong_Stroke_90_CI_AI))
-- 0xA4B8 AED4 A46A A77C 7C
今回は、 "City"値の最後に来る区切り文字を保持しました(そのため、区切り文字が4番目の文字の後続バイトと同じバイト値であることが明確になります)。 4番目の文字坑
は、コードページ950では0xA77C
としてエンコードされます。これが、4番目の文字だけが "?"と表示される理由です。
したがって、これはmightがSSISのバグである可能性があります。または、構成の問題である可能性があります。この1列だけでなく、ファイル全体がコードページ950であることを示す方法はありますか?テキストファイルの観点から列ごとにコードページを扱うことは意味がありません。ファイル全体は、その1つの列だけでなく、コードページ950としてエンコードされます。役立つデリミタを変更することは可能ですが、デリミタは2バイト文字の有効な後続バイト値としてエンコードできるため、問題が遅延する可能性があります。 OPENROWSET
が正しく機能することを考えると、これもcanであると信じる必要があります(ただし、OPENROWSET
のファイルのエンコーディングを設定していませんが、列だけなので、これはまだSSISバグである可能性があります)。
SSIS内でファイルのエンコーディングを設定するには、以下を試してください。
また、「出力列」の下の「CITY」列を確認し、「Fast Parse」ではなく 「Standard Parse」 を使用していることを確認します(「Fast Parse」はロケールに依存しないため)。