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版の扱いが始めてなので環境的な部分が
悪いのかも知れませんが、現状何を対応すればいいのか
糸口が見つからず、書き込みした次第です。
何か思い当たる事象や設定箇所はありますでしょうか?
よろしく、お願いします。
> 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 の内容とともに、それぞれ何点か、具体的に提示できますでしょうか。
追記:
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 の方が良いのかも?
横から失礼します
>(oo4o は、文字コードの扱いが不安なので使っていなかったりする)
よろしければ、このご発言について後学のために補足頂けませんでしょう
か?
素早い回答ありがとうございます。
本日、掲載されていたヒント等を見回って、色々調査しました。
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
教えて貰うばかりでは、あれですので、今回調査した結果ですが
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の扱える範囲外コードは
使用できない事が確認できました。
なので、この結果をもって、なんかまたいい方法を
考える事にします・・・(。-_-。)
ありがとうございました。
一点追記。
DBへ正常にデータが書き込まれている時(UNICODEにて)
ORACLE 10gR2に付属のODBCドライバ経由で
ACCESSのリンクテーブルを張った場合には
正常にデータを読み取る事ができました。
そりゃACCESS提供の古いODBCドライバじゃ
この状況下では使えないよね…NVARCHARとか未対応だし
>>>>(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
再び、どうもです。
> 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に置き換えるに楽な方法が無いか
周りと調整しようかな…と考えている状況です。
> サロゲートぽくないのですが、
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サーバ上の設定だけで完結させられるかも。
> 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 でも良いけれど)
ここら辺は、ピンと来てないので、精通者に聞いてみます。。。
ありがとうございました。
お世話になっております。
>残念ながら、具体的にどの文字がどのように化けてしまうのか、といった
>詳細な資料を残していません。すみません。
>そもそも当時は、私自身は DB 管理者ではなかったので、詳細な設定等は
>知らなかったりします。
>
>当方としては、oo4o では文字化けの問題を解決させることができず、
>しかも調査時間の関係上、文字化けの詳細なプロセスまでを検証する時間を
>持てなかった(ので、問題の少ない ADO.NET を採用した)、というだけです。
すみません、資料や設定等を要求するつもりはありませんでした(汗
およそのいきさつが判りましただけで自分としては充分です。
このスレッドでのお二人のやり取りは勉強になります。m(_)m
> ビックエディアンがどうのこうのと記事が書かれていたのは
> 何度か見た事があるのですが、まだ意味が掴めていなくて
このあたりが参考になるかと。
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
のように調べることができます。
お返事遅くなりました(三連休にて)。
頂いた情報から、さらに調べてみます。
ありがとうございました。
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は、どうなるか不明ですけどね。。。
(調べていない)
ツイート | ![]() |