連載
» 2009年01月21日 00時00分 UPDATE

Oracleトラブル対策の基礎知識(5):文字化けに関するトラブルに強くなる【基礎編】 (3/3)

[渡部亮太,株式会社コーソル]
前のページへ 1|2|3       

データ格納における文字化け

 クライアントのNLS_LANGのキャラクタセットとOracle Databaseのデータベースキャラクタセットが異なる場合に実行されるOracle内部の文字コード変換処理において、クライアント側で入力された文字が、データベース側のキャラクタセットでは対応していない場合に発生する文字化けのパターンです。

 先に説明したとおり、NLS_LANGのキャラクタセットとデータベースキャラクタセットの値が異なる場合、クライアントからデータを格納するとき、クライアント側で文字コード変換が発生します。この処理は、図4の(1)の処理に相当します。NLS_LANGのキャラクタセットの対応文字種に含まれているが、データベースキャラクタセットの対応文字種に含まれない一部の文字については、文字コード変換が正常に実行できません。

 典型的な例としては、データベースキャラクタセットJA16EUCのデータベースに対して、シフトJISの「(1)」(まるいち)などの「丸囲み文字」を格納する場合があります。

 この文字はいわゆる「NEC特殊文字」と呼ばれる種類の文字で、Windows環境のシフトJISで利用可能であり、OracleにおいてもJA16SJISキャラクタセットで対応していますが、JA16EUCキャラクタセットでは対応していません。このため、Windows環境などのクライアントにおけるNLS_LANGのキャラクタセットがJA16SJISである環境から、データベースキャラクタセットがJA16EUCであるOracle Databaseに対して文字「(1)」を格納しようとすると、文字化けが発生します。

キャラクタセット 対応文字種(抜粋)
JA16SJIS
JA16SJISTILDE
ASCII
JIS X 0208(JIS第1・第2水準漢字)
半角カナ(JIS X 0201のカタカナ)
NEC 特殊文字(PC-98文字)
NEC 選定IBM 拡張文字
IBM 拡張文字
ユーザー定義の外字
JA16EUC
JA16EUCTILDE
ASCII
JIS X 0208(JIS第1・第2水準漢字)
半角カナ(JIS X 0201のカタカナ)
JIS X 0112補助漢字
AL16UTF8 Unicode※
表4 キャラクタセットと対応文字種

※:JA16SJIS、JA16EUCの対応文字種はすべて含まれます。

 実際に「(1)」(まるいち)文字を、NLS_LANGキャラクタセットJA16SJISであるクライアントからデータベースキャラクタセットJA16EUCのデータベースに格納してみましょう。

SQL> select * from V$NLS_PARAMETERS where PARAMETER like '%CHARACTERSET%';
PARAMETER                      VALUE
------------------------------ --------------------
NLS_CHARACTERSET               JA16EUC	(A)
SQL> create table tbl1 (pk number(8) primary key , val varchar2(10));
SQL> insert into tbl1 values(1,'あ');
SQL> insert into tbl1 values(2,'(1)');(B)
SQL> commit;
SQL> col DUMP16 format a60
SQL> select pk, val, dump(val, 16) DUMP16 from tbl1;
        PK VAL                  DUMP16
---------- -------------------- ----------------------------------------------
         1 あ                   Typ=1 Len=2: a4,a2
         2 ?                   Typ=1 Len=2: a1,a9 	(C)
リスト2「(1)」(まるいち)文字の文字化け

 リスト2の(A)では、データベースキャラクタセットがJA16EUCであることを確認しています。(B)では、「(1)」(まるいち)文字をINSERTしています。(C)では、INSERTしたデータと、データの内部格納状態を確認しています。

 DUMP()は、データベースに格納されたデータの内部状態を表示するための関数です。DUMP()の詳細はマニュアル「SQLリファレンス」を確認してください。ここでは、引数に「16」を指定して、内部表現を16進数で出力しています。

 リスト2(B)でINSERTしたPK=2の行の確認結果を見ると、VAL列には、正しく「(1)」(まるいち)文字が表示されていません。また、DUMP()の結果から、文字が16進数で0xA1、0xA9で格納されていることが分かります。16進数の0xA1、0xA9は、「?」文字の日本語EUCでの内部表現に相当します。

 実際に、「?」をINSERTしてDUMP()の結果を確認してみると、確かに16進数の0xA1、0xA9となっていることが分かります(リスト3(D))。

SQL> insert into tbl1 values(3,'?');
SQL> commit;
SQL> select pk, val, dump(val, 16) DUMP16 from tbl1;
        PK VAL                  DUMP16
---------- -------------------- -------------------------------------------
         1 あ                   Typ=1 Len=2: a4,a2
         2 ?                   Typ=1 Len=2: a1,a9
         3 ?                   Typ=1 Len=2: a1,a9	(D)
リスト3「?」をINSERTした場合と比較

 クライアントで設定したNLS_LANGのキャラクタセットの対応文字種には含まれるが、データベースキャラクタセットの対応文字種に含まれない一部の文字については、文字コードの変換が正常にできないため、Oracleにより強制的に「?」文字に変換されてしまうことがお分かりいただけたでしょうか。このように、Oracleにおける文字コード変換の際に対応する文字がない場合、特定の文字に変換されます。

 なお、このような状態になった場合、元の文字を復元することはできません。それは、データベースでは元の文字の情報が失われ、すでに「?」文字しか存在していないためです。このような問題を回避するためには、以下のアプローチが考えられます。

1.システムの対応範囲外とする
上記の「(1)」のような、キャラクタセットによって対応/非対応が分かれる文字については、システムの対応範囲外とする。例えば、データベースキャラクタセットJA16SJISのデータベースに、NLS_LANGのキャラクタセットがJA16EUCのクライアントが接続する環境では、システムの対応文字種をASCII、JIS X 0208-1997 (JIS第1・第2水準漢字)、半角仮名(JIS X 0201-1997の片仮名)に限定する

2.すべてのキャラクタセットを限定する
すべてのクライアントのNLS_LANGのキャラクタセット、データベースキャラクタセットを、「(1)」をサポートするキャラクタセットに限定する。例えば、今回のケースでは、すべてのクライアントのNLS_LANGのキャラクタセットとデータベースキャラクタセットをJA16SJIS、JA16SJISTILDEといったシフトJIS系のキャラクタセット、Unicode系のキャラクタセットに限定する

3.すべてのキャラクタセットを統一する
文字コード変換が発生しないように、すべてのクライアントのNLS_LANG、データベースキャラクタセットを統一する

4.Unicodeとしてデータを格納する
Unicodeデータ格納用のデータ型(NCHAR型、NVARCHAR2型)のカラムにUnicodeとして格納する

データ取得における文字化け

 データ取得においても、クライアントのNLS_LANGのキャラクタセットとデータベースキャラクタセットの値が異なる場合はクライアント側で文字コード変換が発生するため、格納の場合と同じメカニズムで文字化けが発生します。この処理は、図1(2)の処理に相当します。対処についてもデータ格納の対処策と同様の対処が考えられます。

データ表示における文字化け

 Oracleレベルではデータが正常に取得できているが、OS/アプリケーション側で、文字データを表示する処理に問題があり発生する文字化けのパターンです。

図6 データ表示における文字化け 図6 データ表示における文字化け

 Oracleは、NLS_LANGに指定したキャラクタセットに対応した文字コードを、アプリケーションが適切に処理できると仮定します。いい換えれば、Oracleは、OS/アプリケーションが実際にその文字コードを適切に処理できるかどうかは特に考慮せず、OS/アプリケーションにNLS_LANGのキャラクタセットの文字コードでデータを出力します。なお、入力の際も同様です。

 このため、OS/アプリケーションが実際には処理できない文字コードをNLS_LANGのキャラクタセットに指定すると、Oracleが入出力する文字データをOS/アプリケーションが処理できないため、文字化けが発生する場合があります。例えば、Windowsのコマンドプロンプト上で動作するSQL*Plus(sqlplus.exe)は、日本語EUCを適切に処理できません。従って、NLS_LANGにJA16EUCを指定すると、文字化けが発生します。

C:\> set NLS_LANG=Japanese_Japan.JA16EUC
C:\> sqlplus test/test
SQL*Plus: Release 10.2.0.3.0 - Production on イミ 7キ・8 12:46:24 2008
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning and Data Mining options
、ヒタワツウ、オ、・゙、キ、ソ。」
SQL>
SQL> col DUMP16 format a60
SQL> select pk, val, dump(val, 16) DUMP16 from tbl1;
        PK VAL                            DUMP16
---------- ------------------------------ ------------------------------------
         1 、「                             Typ=1 Len=3: e3,81,82
         2 。ゥ                             Typ=1 Len=3: e2,91,a0
         9 ??                             Typ=1 Len=2: 3f,3f
         3 。ゥ                             Typ=1 Len=4: f0,a0,80,8b
         8 。ゥ                             Typ=1 Len=4: f0,a0,80,8b
リスト4 Windows環境/SQL*PlusでJA16EUCを指定した場合

 同様に、端末エミュレータ(TeraTerm、Putty、Gnome Terminalなど)でSQL*Plusを実行して、端末エミュレータの文字コード設定を日本語EUCとしたときに、NLS_LANGにJA16SJISを設定すると文字化けが発生します。

 このような問題を回避するためには、以下のアプローチが考えられます。

1.NLS_LANGのキャラクタセットをOS/アプリケーションが対応している文字コードに設定する

2.OS/アプリケーションに文字コード設定が存在する場合は、それらをNLS_LANGのキャラクタセットに統一する

 以上で、Oracleの文字化けについて基礎的な説明を終了します。

最後に

 次回は本稿の内容を踏まえて、「〜(チルダ)」の文字化けに代表されるJavaなどのUnicodeベースのアプリケーションで発生する問題と、Windows Vistaの登場によって現在問題となりつつあるJIS X 0213とサロゲートペアの問題について説明します。

Oracleを本格的に学ぶ前に読んでおくべき1冊

プロとしてのOracle入門

プロとしてのOracle入門

著者:松下 雅、舛井 智行、古賀 加奈
発行:ソフトバンククリエイティブ(2008年10月)
定価:2,079円(税込)
ISBN:978-4-7973-4943-6


本稿の筆者、渡部亮太氏が所属する株式会社コーソルより、『プロとしてのOracle』シリーズ本の2冊目が出版されました。

内容は第4回で紹介した『プロとしての Oracle アーキテクチャ入門』の一歩手前。これからOracleを始めよう! というエンジニア向けです。データベースの成り立ちからOracle の仕組みについて、実際に、インストールや SQL 文を使ってデータベースを触りながら学べます。



前のページへ 1|2|3       

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。