はじめに
Oracle Data Pumpは論理バックアップおよび異なるバージョンやオペレーティング・システムのOracle Database間でデータを安全に転送できる優れたツールです。Oracle Database 10g以降の標準機能(圧縮機能や暗号化には別途追加ランセンスが必要)であり、従来の Export / Importユーティリティの機能を引き継いでいます。本資料では、Data Pumpユーティリティを使ったデータ移行時に予期せぬ文字コード変換が発生することを示しています。
文字コード(エンコード)の変換機能
Data Pumpはエンコードが異なるデータベース間で自動的に文字コードの変換を行います。変換処理はImport (impdp) 時に行われます。環境変数NLS_LANGには依存せず、自動的にインポート先のエンコードに変換されて格納されます。このためData Pumpにはエンコード関連を指定するパラメーターはありません。
問題となる文字
Microsoft Windows等で広く使われてきたShift_JISには様々な拡張が行われました。以下のような文字集合が拡張されています。
文字集合 | コードポイント |
---|---|
NEC特殊文字 | 8740 - 879C |
NEC選定IBM拡張文字 | ED40 - EEFC |
IBM拡張文字 | FA40 - FC4B |
上記のうち、例えば以下の文字は同一のグリフにもかかわらず、IBM拡張文字とNEC選定文字両方にコードが定義されています。
文字 | IBM拡張文字 | NEC拡張文字 | Unicode |
---|---|---|---|
Ⅰ | 0xFA4A | 0x8754 | \u2160 |
Ⅱ | 0xFA4B | 0x8755 | \u2161 |
Ⅲ | 0xFA4C | 0x8756 | \u2162 |
Ⅳ | 0xFA4D | 0x8757 | \u2163 |
Ⅴ | 0xFA4E | 0x8758 | \u2164 |
Ⅵ | 0xFA4F | 0x8759 | \u2165 |
Ⅶ | 0xFA50 | 0x875A | \u2166 |
Ⅷ | 0xFA51 | 0x875B | \u2167 |
Ⅸ | 0xFA52 | 0x875C | \u2168 |
Ⅹ | 0xFA53 | 0x875D | \u2169 |
ⅰ | 0xFA40 | 0xEEEF | \u2170 |
ⅱ | 0xFA41 | 0xEEF0 | \u2171 |
ⅲ | 0xFA42 | 0xEEF1 | \u2172 |
ⅳ | 0xFA43 | 0xEEF2 | \u2173 |
ⅴ | 0xFA44 | 0xEEF3 | \u2174 |
ⅵ | 0xFA45 | 0xEEF4 | \u2175 |
ⅶ | 0xFA46 | 0xEEF5 | \u2176 |
ⅷ | 0xFA47 | 0xEEF6 | \u2177 |
ⅸ | 0xFA48 | 0xEEF7 | \u2178 |
ⅹ | 0xFA49 | 0xEEF8 | \u2179 |
№ | 0xFA59 | 0x8782 | \u2116 |
㈱ | 0xFA58 | 0x878A | \u3231 |
﨑 | 0xFAB1 | 0xED95 | \uFA11 |
髙 | 0xFBFC | 0xEEE0 | \u9AD9 |
文字コードJA16SJISから文字コードJA16SJISTILDEに移行
文字コードJA16SJISのデータベースと文字コードJA16SJISTILDEのデータベースを作成し、Data Pumpによるデータ移行を行います。この2つの文字コードは'~'の扱い以外は同一のコード体系を持っています。
両方の文字コードを格納
文字コードJA16SJISで作成されたデータベースに、NEC拡張文字とIBM拡張文字でラテン数字のⅠを格納します。見た目ではわかりませんが、DUMP関数で格納コードを確認すると正しく格納されています。
SQL> SELECT c1, DUMP(c1, 16) DMP FROM encode1 ;
C1 DMP
-------------------- --------------------
Ⅰ Typ=1 Len=2: fa,4a ← IBM拡張コード
Ⅰ Typ=1 Len=2: 87,54 ← NEC拡張コード
Data Pumpでデータ移行
次に Data Pumpユーティリティを使って、エンコードJA16SJISのデータベースからエンコードJA16SJISTILDEのデータベースへデータの移行を行ってみます。
# Export
$ export ORACLE_SID=sjis1
$ expdp SCOTT/pass DIRECTORY=DATA_PUMP_DIR DUMPFILE=encode1.dmp TABLES=encode1
# Import
$ export ORACLE_SID=tilde1
$ impdp SCOTT/pass DIRECTORY=DATA_PUMP_DIR DUMPFILE=encode1.dmp TABLES=encode1
格納文字コードを確認
文字コードを確認します。
SQL> SELECT C1, DUMP(c1, 16) DMP FROM encode1 ;
C1 DMP
-------------------- --------------------
Ⅰ Typ=1 Len=2: 87,54
Ⅰ Typ=1 Len=2: 87,54
上記のように、NEC拡張文字のコードに変更されて格納されていることがわかります。
JA16SJISとJA16SJISTILDEのようにほとんど同一の文字コードの場合でも、Data Pump による移行では文字コード変換が行われ、意図しない文字コード変換が起こる可能性があります。