CHAR,NCHAR,VARCHAR2 におけるコード変換について

コード変換の手順

クライアントのコードセットは OS では LANG で、 oracle では NLS_LANG 環境変数で指定します。
また、データベースのコードセットは、データベース作成時に指定します。

基本的には、以下の手順でコート変換されます。

唯一の例外は、クライアントが java プログラムのときです。 詳細は、jdbc thin ドライバでの接続の項で記述します。

テスト環境

すべてのテストは、 クライアント macS12345 PRO817 から DB サーバ macA ORA816 への TCP 接続です。
各例の項目をクリックすると、実際に転送されたパケットを見られます。

サイドホスト名 ORACLE_SID NLS_LANGLANGポート
クライアントmacS12345 PRO817 Japanese_Japan.JA16SJIS Ja_JP(SJIS)短命ポート
DB サーバmacAORA816 Japanese_Japan.JA16EUC ja (EUC)1816

各例の図の ⇔|⇔ は、ネットワーク接続を意味し、 ここでパケットを取得しました。

sqlplus taka/taka@macA816

Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
に接続されました。

SQL> desc コード;
 名前                                      NULL?    型
 ----------------------------------------- -------- ----------------------------
 コード1                                           VARCHAR2(2)
 SJIS                                               CHAR(10)
 EUC                                                CHAR(10)
 UNICODE                                            CHAR(10)
 UTF8                                               CHAR(10)
 句点                                               NUMBER(4)

SQL> exit

接続別手順

  1. sqlplus での接続
  2. jdbc での接続

sqlplus での接続

sqlplus taka/taka@macA816
SQL> select * from コード;

コ SJIS       EUC        UNICODE    UTF8             句点
-- ---------- ---------- ---------- ---------- ----------
あ 82A0       A4A2       3042       E38182            402
ア 8341       A5A2       30A2       E382A2            502
A 8260       A3C1       FF21       EFBCA1            601
亜 889F       B0A1       4E9C       E4BA9C           1601

SQL> exit

  1. sqlplus から接続文字列で別のマシンに接続する場合

    環境 クライアント DB サーバ データ
    ベース
    NLS_LANG=SJIS sqlplus

    SJIS ⇔ EUC
    ⇔|⇔ oracleORA816

    EUC
    EUC


  2. sqlplus からデータベースリンクで別のマシンに接続する場合

    環境 クライアント側 DB サーバ データ
    ベース
    NLS_LANG=SJIS sqlplus

    SJIS ⇔ EUC
    oraclePRO817

    EUC
    ⇔|⇔ oracleORA816

    EUC
    EUC


jdbc での接続

jdbc を介して oracle へ接続する方法は、以下の2通りですので、 これらについて説明します。

> java jdbc thin
接続方法:jdbc:oracle:thin:@macA:1816:ora816

実行文:select * from コード
あ : 82A0       : A4A2       : 3042       : E38182
ア : 8341       : A5A2       : 30A2       : E382A2
A : 8260       : A3C1       : FF21       : EFBCA1
亜 : 889F       : B0A1       : 4E9C       : E4BA9C

実行文:select * from コード where EUC like '%A1%'
亜 : 889F       : B0A1       : 4E9C       : E4BA9C

> java jdbc oci
接続方法:jdbc:oracle:oci8:@macA816

実行文:select * from コード
あ : 82A0       : A4A2       : 3042       : E38182
ア : 8341       : A5A2       : 30A2       : E382A2
A : 8260       : A3C1       : FF21       : EFBCA1
亜 : 889F       : B0A1       : 4E9C       : E4BA9C

実行文:select * from コード where EUC like '%A1%'
亜 : 889F       : B0A1       : 4E9C       : E4BA9C

  1. thin ドライバでの接続

    java プログラムから thin ドライバを経由してデータベースに接続する場合、 データベースのコードセットから oracle Unicode である UTF8 への変換は、 DB サーバで処理されます。
    なぜなら、クライアント側が java であることから、 java VM 内部での文字コード Unicode から LANG への変換だけだからです。

    環境 クライアント側 DB サーバ データ
    ベース
    LANG=SJIS java

    SJIS ⇔ Unicode
    thin ドライバ

    Unicode ⇔ UTF-8
    ⇔|⇔ UTF-8 ⇔ EUC EUC


  2. oci ドライバでの接続

    java プログラムから oci ドライバを経由してデータベースに接続する場合は、 thin ドライバとは異なり、 クライアント側に DBMS クライアントライブラリがあり、 この中のネイティブメソッドで、 データベースのコードセットから oracle Unicode である UTF8 に変換します。
    クライアントの java プログラムでは java VM 内部での文字コード Unicode から LANG への変換だけとなります。

    環境 クライアント側 DB
    サーバ
    データ
    ベース
    LANG=SJIS java


    SJIS ⇔ Unicode
    oci
    ドライバ


    Unicode ⇔ UTF-8
    DBMS
    ライブラリ


    UTF-8 ⇔ EUC
    ⇔|⇔ EUC EUC


    なお、上記2つのドライバでの接続で結果が異なる場合は、 ドライバのバグと考えられます。

Unicode 2バイト方式の文字コードで java の内部コードとして使われています
ISO 10646 4バイト方式の文字コードです
UTF-8 ASCII と互換性のある Unicode




関連リンク

  1. UTF-8
  2. java 講座

関連項目

iconv(1),iconv(5), iconv_unicode(5),iconv_ja(5)

用語の説明

Unicode
Unicode は、世界中の文字を1つの文字コードに収めるという理念のもとに、 16 進数4桁のコード (0X0000 〜 0xFFFF が可能) を割り振った。 Unicode は、1991 年に Unicode 1.0 が製作されて以来、1993 年に Unicode 1.1、 1996 年に Unicode 2.0 が製作された。

これに対し ISO 10646 は、すべての文字に 16 進数8桁のコード (0X00000000 〜 0x7FFFFFFFF が可能) を割り振ったが、 31 ビットで1文字を表す点が Unicode と異なる。

ただし、現時点で ISO 10646 に含まれている 34168 文字はすべて Unicode 1.1 の文字であり、しかも Unicode 1.1 でのコードを XXXX とすると、0000XXXX がそのまま ISO 10646 のコードになっている。 ISO 10646の文字集合。UCS:Universal Multiple-Octet Coded Character Set

UCS-2
UCS-4のうち2bytesであらわせる基本部分(BMP)のみを抽出したサブセット文字集合。 あるいは、その2バイトをそのまま文字符号とする符号化法を指す。 この場合、エンディアンによって、LittleEndian型とBigEndian型があり、 テキストの先頭に0xfeffを配置して区別できる (L型なら「0xff、0xfe」、B型なら「0xfe、0xff」になる)。 Windowsにおける標準的なUnicode。

UCS-4
 4 バイト(厳密には31bit)の領域を持つ文字集合。本来の意味でのUCS。  あるいは、その4バイトをそのまま文字符号とする符号化法を指す。 この場合、エンディアンによって、LittleEndian型とBigEndian型があり、 テキストの先頭に0x0000feffを配置して区別できる (L型なら「0xff、0xfe、0x00、0x00」、B型なら「0x00、0x00、0xfe、0xff」になる)。

UTF-8
UTF-8 は Unicode に以下の演算をして、ASCII と上位互換をとったコードです。
  1. Unicode が 0000 〜 007F
    1 バイトのままのコード
  2. Unicode が 0080 〜 07FF
    Unicode を2進数に変換した値を 0000 0XXX XXYY YYYY とすると、 2進数で 110XXXXX を1バイト目とし、10YYYYYY を2バイト目とする。
  3. Unicode が 0800 〜 FFFF
    Unicode を2進数に変換した値を XXXX YYYY YYZZ ZZZZ とすると、 2進数で 1110XXXX を1バイト目とし、10YYYYYY を2バイト目とし、 10ZZZZZZ を3バイトとする。

参考書  

  1. 文字コードの世界  東京電気大学出版局 3600