UNICODE文字をオラクルで扱うには?

解決


UNICODE調査隊  2007-09-19 05:19:21  No: 143898

OS:VISTA
ORACLE:10gRelese2、
データベースの文字セット(NLS_CHARRACTERSET):AL32UTF8
接続に、上記Oracleのoo4o(OracleInProcServer5.0)
プログラムツール:VB NET2005
データベースの項目には、UNICODEでも対応できるよう
大きめのサイズでVARCHAR(100 CHAR)として作成済み

この状態で、テキストボックスに、シフトJISに無い
文字列コード1文字を入力し、ボタンをクリックする事で
昔ながらのoo4oで行われるプログラムでデータを書き込み
を行うプログラムを作成しました。
エラーも発生せず、データベースへ書き込む事ができます。

書き込んだデータを、同様にoo4o方式でCreateDynasetで読み出すと
シフトJISに対応されていない文字コードの場合
?となって、文字化けして表示されてしまいます
(サロゲート文字等?)。シフトJISが用意されている文字は
記号も含め問題なさそうです。

環境的にはUNICODEに対応可能なシステムでテストして
検証をしているつもりでしたが、上記問題が発生していて
色々調査してみたものの、検討がついていません。
自分はVisualStudio NET版の扱いが始めてなので環境的な部分が
悪いのかも知れませんが、現状何を対応すればいいのか
糸口が見つからず、書き込みした次第です。

何か思い当たる事象や設定箇所はありますでしょうか?

よろしく、お願いします。


魔界の仮面弁士  2007-09-19 07:13:52  No: 143899

> UNICODE文字をオラクルで扱うには?
そのあたりの情報は、VB 系の掲示板で質問するよりも、
Oracle の KROWN を探したり、OTN の掲示板を検索する方が、
より具体的な情報を得やすいかと思います。

> データベースの項目には、UNICODEでも対応できるよう
> 大きめのサイズでVARCHAR(100 CHAR)として作成済み
テーブル名等にまで Unicode が必要ならば仕方ないですが、
データのみが Unicode で保持されていれば十分というのであれば、
DB 自体は JA16SJISTILDE で作っておいて、Unicode データは
NVARCHAR2(100 CHAR) 列に格納させた方が、運用が楽かも知れません。

> データベースの文字セット(NLS_CHARRACTERSET):AL32UTF8
AL32UTF8 だと、面倒ではありませんか?
UTF8 だと、CJKの漢字は 3バイト、ギリシャ/ロシア文字は 2バイト、
英数字は 1バイトですよね。容量計算が面倒ですし、無駄が多いような。

> 接続に、上記Oracleのoo4o(OracleInProcServer5.0)
環境変数は変更されましたか?

> エラーも発生せず、データベースへ書き込む事ができます。
書き込んだ内容は正しいですか? SQL/Plus などから
  SELECT DUMP(対象列, 1016) AS F1 FROM 対象テーブル
を実行して、AL32UTF8 形式で記録されていることを確認してください。

正しい CharcterSet で記録されていれば、読み込み処理の時点で
問題が発生していることになりますし、あるいは、CharcterSet が
他の形式(JA16SJIS や JA16SJISTILDE など)で記録されているようなら、
書き込み時、または読み書き双方に問題があることになります。

また、CharcterSet が正しい場合には、バイナリ値が正常であるかも
確認してみてください。バイナリ値まで正しいのであれば、完全に
読み込み処理のみの問題です。

> (サロゲート文字等?)。
サロゲートペアに該当する文字を使っておられるのですか…?
具体的には、何という文字を入力されたのでしょうか。

大丈夫な文字と、大丈夫では無い文字(の 16進数コード値)を、
DUMP の内容とともに、それぞれ何点か、具体的に提示できますでしょうか。


魔界の仮面弁士  2007-09-19 09:01:52  No: 143900

追記:

oo4o だと NCHAR / NVARCHAR2 を扱えないそうですね。
http://otndnld.oracle.co.jp/document/products/oracle10g/102/generic/B19227-07/oo4o_readme.htm

> DB 自体は JA16SJISTILDE で作っておいて、Unicode データは
> NVARCHAR2(100 CHAR) 列に格納させた方が、運用が楽かも知れません。
この場合、接続には oo4o を使うのではなく、ADO.NET 系テクロノジである
System.Data.OracleClient もしくは ODP.NET (Oracle.DataAccess.Client) で
接続するという意味です。

少なくとも当方ではこれで運用しており、Shift_JIS に無い文字も使えています。
(oo4o は、文字コードの扱いが不安なので使っていなかったりする)

> 環境変数は変更されましたか?
環境変数の設定方法については、このあたりを参照。
http://shodai.hp.infoseek.co.jp/oracle_global/oracle_global.html
http://otndnld.oracle.co.jp/easy/dotnet/extra/oo4o_extra.pdf

ただ、oo4o は入力データを NLS_LANG から Unicode に一旦変換して、
DB の CHARACTER SET に変換しなおすといった作業をしているそうなので、
それらがどのように作用するのかは、私も細かくは調べていません。m(_ _)m

というよりは、下記を参考にした上で、
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19218-02/ch3globenv.htm
「NLS_LANG設定とデータベース・キャラクタ・セットを一致させる必要があるかどうか」
あたりを参考に、幾つかの組み合わせを試してみようとしたのですが、VB2005 + ADO.NET では、
対して設定せずとも、文字化け等が発生しなかったので、調査時間の都合もあって、
そこで調査を打ち切ってしまい、oo4o までは調べていなかったり。(手抜き)

なお、DB および環境変数を AL32UTF8 にした場合においては、
もしも oo4o 側が改善されたとしても、SQL*PLUS (sqlplus.exe)が
文字化けしたり、予期出来ないエラーで停止する事が報告されています。
なので、環境変数は JA16SJIS または JA16SJISTILDE の方が良いのかも?


HogeHoge  2007-09-19 19:06:09  No: 143901

横から失礼します

>(oo4o は、文字コードの扱いが不安なので使っていなかったりする)

よろしければ、このご発言について後学のために補足頂けませんでしょう
か?


UNICODE調査隊  2007-09-20 03:09:51  No: 143902

素早い回答ありがとうございます。
本日、掲載されていたヒント等を見回って、色々調査しました。

oo4oを使うのは、システム移行で元がoo4oを使用している為で
新規のシステムであれば、ADO.NETなりODP.NETを利用したかと思います。
残念ながら、これに伴う大幅な工数が用意されない事情があり
可能な限りは、現行のまま進めていける方法を模索していた事情があります。

>> (サロゲート文字等?)。
> サロゲートペアに該当する文字を使っておられるのですか…?
> 具体的には、何という文字を入力されたのでしょうか。
> 大丈夫な文字と、大丈夫では無い文字(の 16進数コード値)を、
> DUMP の内容とともに、それぞれ何点か、具体的に提示できますでしょうか。

テストで使用した文字は以下の通りで、文字化けしているのは
SJISの無いものと考えてください(WEBベースだと表示されるな…)。
01) a:U+0061
02) ア:U+FF71
03) あ:U+3042
04) 亜:U+4E9C
05) 〒:U+3012
06) ㎡:U+33A1
07) Ⅹ:U+2169
↓===SJISに無いコード===
08) 㐂:U+3402
09) 鸞:U+F920
10) 〠:U+3020
11) ㎥:U+33A5
12) Ⅺ:U+216A
13) 𠂢:U+200A2


UNICODE調査隊  2007-09-20 03:29:27  No: 143903

教えて貰うばかりでは、あれですので、今回調査した結果ですが
DBを丸ごとUNICODE対応のAL32UTF8で作成したものと
ベースJA16SJISTILDEで作成し、該当項目のみUNICODE化するために
NVARCHARを使用したもので、それぞれ01〜13のコードをDBへ記録しました。

またクライアント環境も頂いた情報からJA16SJISTILDEで設定したものと
ORACLEは認めていないようですが、AL32UTF8で環境を設定して
データを書き込みしました。

NVCHARを利用した項目例
Typ=1 Len=2 CharacterSet=AL16UTF16:XX XX
全体をUNICODE化した項目例
Typ=1 Len=3 CharacterSet=AL32UTF8:XX XX XX

簡単に調査結果を表示しますと、、、
書き込んだ内容と、結果を見比べた事から
01〜07までは、正常にデータを書き込む事ができますが
08〜13では、DBとクライアント共にAL32UTF8にして
データを更新しないと、データの欠損が発生する事が確認できました。

また正常に書き込み正常に表示する事はプログラム上の操作では
可能でしたが、SQL/PLUS等の画面からは文字化けの状態で
操作できず、ODBC接続で確認しても?表示され、意味を成さない事も
確認できました。

つまり、oo4oを利用する以上は、シフトJISの扱える範囲外コードは
使用できない事が確認できました。

なので、この結果をもって、なんかまたいい方法を
考える事にします・・・(。-_-。)

ありがとうございました。


UNICODE調査隊  2007-09-20 04:10:16  No: 143904

一点追記。

DBへ正常にデータが書き込まれている時(UNICODEにて)
ORACLE 10gR2に付属のODBCドライバ経由で
ACCESSのリンクテーブルを張った場合には
正常にデータを読み取る事ができました。

そりゃACCESS提供の古いODBCドライバじゃ
この状況下では使えないよね…NVARCHARとか未対応だし


魔界の仮面弁士  2007-09-20 21:25:34  No: 143905

>>>>(oo4o は、文字コードの扱いが不安なので使っていなかったりする)
>>> よろしければ、このご発言について後学のために補足頂けませんでしょうか?

残念ながら、具体的にどの文字がどのように化けてしまうのか、といった
詳細な資料を残していません。すみません。
そもそも当時は、私自身は DB 管理者ではなかったので、詳細な設定等は
知らなかったりします。

当方としては、oo4o では文字化けの問題を解決させることができず、
しかも調査時間の関係上、文字化けの詳細なプロセスまでを検証する時間を
持てなかった(ので、問題の少ない ADO.NET を採用した)、というだけです。

それが、先に書いた
>> そこで調査を打ち切ってしまい、oo4o までは調べていなかったり。(手抜き)
に繋がって来ます。

# ちなみに、その ADO.NET 製の案件というのは、クライアント/サーバの
# モデルではなく、Webサービスを経由した N階層のシステムでした。
# ゆえにクライアント側には、Oracle Client を導入していません。

> 残念ながら、これに伴う大幅な工数が用意されない事情があり
個人的には、oo4o の方が工数がかかるように思います。

oo4o は COM のオブジェクトなので、OraSession, OraDynaset, OraParameters, OraParameter 等々、
それぞれのオブジェクトを、使用後に Marshal.ReleaseComObject しないと、オブジェクトが
正しく解放されません。(しかも、解放漏れの検証が難しいので、デバッグが面倒になる)

また、oo4o は(ODP.NET とは違って)ADO.NET との互換性も無いため、たとえば DataGridView 等を
使おうとした場合に、自分で System.Data.DataTable 等にループで格納するなどの
余計な手間がかかる事が予想されます。

> テストで使用した文字は以下の通りで、文字化けしているのは
えぇと、先に
>> DUMP の内容とともに、
と書いたように、Oracle 側に格納後の情報も一緒に欲しかったのです。

それが分からないと、書き込み時の問題か読み込み時の問題かの判断が付かないので。

# 実際には、OS の問題か .NET の問題か oo4o の問題か Oracle の問題かというレベルまで
# 切り分けねばならないので、それ以外の情報も必要になってくるのですが。

> ↓===SJISに無いコード===
あれ? 検証対象の文字はこれだけですか?
問題点に挙げられていた、肝心の「サロゲート」な文字が無いようですけれども…。

たとえば、U+233D0 : [木]+[夕] とかはどうでしたか?
(UTF-16 では D84C,DFD0 で、UTF-8 では F0,A3,8F,90 となる文字です)
http://www.unicode.org/cgi-bin/refglyph?24-233D0

それと、この手の問題は、格納/取得できるかどうかだけを検証すれば良いというものではなく、
WHERE での = 比較や LIKE 比較ができるかや、各種関数の対応なども調べねばならないかと。
http://www.thinkit.co.jp/cert/article/0707/14/1/3.htm


UNICODE調査隊  2007-09-21 03:32:47  No: 143906

再び、どうもです。

> oo4o は COM のオブジェクトなので、OraSession, OraDynaset, 
> OraParameters, OraParameter 等々〜〜〜〜〜〜
> (しかも、解放漏れの検証が難しいので、デバッグが面倒になる)

これは、別調査隊が把握しているようなので、聞いておきます
すみません(^-^;

> oo4o は(ODP.NET とは違って)ADO.NET との互換性も無いため〜〜〜
> 余計な手間がかかる事が予想されます。

対象のシステムがこういった、手の込んだ物を使っていないようなので、今回については、大丈夫かと思ってます。

> たとえば、U+233D0 : [木]+[夕] とかはどうでしたか?

字型としては、サロゲートぽくないのですが、13)が該当に
あたると思ってます。
これがunicodeで格納された内容を見てみると
F0 A0 82 A2
にて格納されています。
データ格納の段階で、実際2文字分の要求をされましたし。
時間があれば、上記の文字も行ってみます。

同一文字で、異常なデータ格納パターンで見られたのは
FF 1F FF FF や
EF BC 9F EF BC 9F などです(共に13)です)

> 比較や LIKE 比較ができるかや〜〜〜
簡単な実験は行ってますが、そういえばSJIS外のパターンでチェックし忘れてました。明日にでも実験しておきます。

ですが、、、oo4oで正常に格納できる設定というのが
DBもクライアントもUNICODEにして、なおかつUNICODEを格納する
項目はVARCHAR2 (10 CHAR)のように設定しないとODBCやら
なにやら色々不都合が出てしまうのが、分かったので
oo4oを止めるか、J90相当の文字までしか使えないように
縛るしかなさそうなんです。

とりあえず現状では、oo4oで続ける事は、かなりトラブルの原因と
なりそうで、ソースコードをODP.NETに置き換えるに楽な方法が無いか
周りと調整しようかな…と考えている状況です。


魔界の仮面弁士  2007-09-21 05:47:58  No: 143907

> サロゲートぽくないのですが、
UTF-8 や UTF-32 では、サロゲートペアは採用されていません。
(UTF-16 のサロゲートペアは、UTF-8 では 4バイトで表現されます)

> 13)が該当にあたると思ってます。
おっおーう。完全に見落としてました。申し訳ない。

U+200A2 のエンコーディングは、それぞれ
  UTF-8: F0 A0 82 A2
  UTF-16: D840 DCA2
  JIS X 0213: 2面1区11点
ですね。

> これがunicodeで格納された内容を見てみると
> F0 A0 82 A2
> にて格納されています。
つまり、Dump 結果が
  Typ=1 Len=4 CharacterSet=AL32UTF8 : f0,a0,82,a2
となるように格納することができた、ということでしょうか?

ということは、格納処理は正常に動作するようになったのですね。
あとは読み込みのみ…。

> DBもクライアントもUNICODEにして、
oo4o 依存の既存資産が多くて、ADO.NET 化の工数が取れないようであれば、
使いどころを変えて、oo4o は Oracle Server 上のみで用いるようにする、とか。

データ処理を WebService 化しておいて(.NET Remoting でも良いけれど)、
クライアント側のアプリには、oo4o 系のオブジェクトを一切操作させないようにすれば、
oo4o での文字コード変換の問題は、DBサーバ上の設定だけで完結させられるかも。


UNICODE調査隊  2007-09-21 18:31:20  No: 143908

> U+200A2 のエンコーディングは、それぞれ
>    UTF-8: F0 A0 82 A2
>    UTF-16: D840 DCA2
>    JIS X 0213: 2面1区11点

コード変換で、ビックエディアンがどうのこうのと記事が書かれていたのは
何度か見た事があるのですが、まだ意味が掴めていなくて
確実にコードを把握できるほどじゃないのが、痛い所ですが
他のデータと見比べたり、表示された状態からあってるな〜
っていう感じでして。
もし、よろしければ、コレっというページを紹介して頂けたら
助かります。

> Typ=1 Len=4 CharacterSet=AL32UTF8 : f0,a0,82,a2
> となるように格納することができた、ということでしょうか?

ですです。

> ということは、格納処理は正常に動作するようになったのですね。
> あとは読み込みのみ…。
読み込み書き込みは、クライアント側の環境設定をAL32UTF8に設定すると
されるのは、できる事を把握できたのですが
このままだと、SQL/PLUSとかが、まったく使えない状態になるのが
問題なんですよねぇ…ISQLとかもあるようですが…
使用禁止!とかならいいのかも知れないけど
メンテナンスが出来なくなってしまいますから(^-^;

> データ処理を WebService 化しておいて(.NET Remoting でも良いけれど)
ここら辺は、ピンと来てないので、精通者に聞いてみます。。。

ありがとうございました。


HogeHoge  2007-09-21 20:04:34  No: 143909

お世話になっております。

>残念ながら、具体的にどの文字がどのように化けてしまうのか、といった
>詳細な資料を残していません。すみません。
>そもそも当時は、私自身は DB 管理者ではなかったので、詳細な設定等は
>知らなかったりします。
>
>当方としては、oo4o では文字化けの問題を解決させることができず、
>しかも調査時間の関係上、文字化けの詳細なプロセスまでを検証する時間を
>持てなかった(ので、問題の少ない ADO.NET を採用した)、というだけです。

すみません、資料や設定等を要求するつもりはありませんでした(汗
およそのいきさつが判りましただけで自分としては充分です。

このスレッドでのお二人のやり取りは勉強になります。m(_)m


魔界の仮面弁士  2007-09-22 10:19:39  No: 143910

> ビックエディアンがどうのこうのと記事が書かれていたのは
> 何度か見た事があるのですが、まだ意味が掴めていなくて
このあたりが参考になるかと。
http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm

> もし、よろしければ、コレっというページを紹介して頂けたら助かります。
Oracle 関連については知りませんが、ユニコード関連については、
私は、ユニコード コンソーシアム で情報を得ています。
http://www.unicode.org/standard/translations/japanese.html

たとえば今回の U+200A2 のエンコーディングを知りたければ、
http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=200A2
のように調べることができます。


UNICODE調査隊  2007-09-26 01:38:03  No: 143911

お返事遅くなりました(三連休にて)。

頂いた情報から、さらに調べてみます。

ありがとうございました。


UNICODE調査隊  2007-10-05 01:27:24  No: 143912

ODP.NETを使って更新テスト

の結果は、SHIFTJISベースのDBに
NVARCHAR2にて列項目を作成し
UNICODEのデータを書き込む。

NVARCHAR2がUNICODEで格納する項目だから
成功する!
・・・と思ったんだけどねぇ・・・事実は奇ナリ

Oracle10.2.0.3.0
ODP.NET10.2.0.2.21
SJIS範囲外のデータを書き込んだ時、データ破損状態にて
格納されました。
U+3402とかね。サロゲートU+200A2はもちろん、言うまでも無く。

DBの文字コードがUNICODEベースの物であれば
正常に書き込まれている。

よって、上記バージョンでは
SHIFTJISベースのDBに、UNICODE対応の
NVARCHAR2を使った項目を用意しても
データは保障されない。。。

もちろん、列項目の大きさは
テストデータを入れるには十分な大きさを
取った状態で行っている。

という事で・・・SHIFTJISにNVARCHAR2つかって
UNICODEを保存すればいい計画は、暗礁に乗り上げましたとさ。
OLEBは、どうなるか不明ですけどね。。。
(調べていない)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加