Apache Derby インポートプロシージャ使用時の文字コード指定
MementoWeaver開発記
MWのデータ移行Pgmも(とりあえずAlbumだけは)ひとまず出来たので、出来たCSVをDerbyにインポートしてみたが、またしても嵌ったので嵌りメモ。
自ら望んだとはいえ、毎回はまる...。
環境
Javaのバージョン
C:\Program Files\Java\jdk1.7.0_13\bin>java -version java version "1.7.0_13" Java(TM) SE Runtime Environment (build 1.7.0_13-b20) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
ijのバージョン
C:\Program Files\Java\jdk1.7.0_13\db\bin>ij ij バージョン 10.8
テーブル定義
色々再現したのはTagged_Material(タグ付素材)テーブル。
VARCHAR(256)のMEMOフィールドを中心に嵌った。
嵌ったポイント
- derbyへインポートが行えないデータが存在する
- インポートに成功したデータが文字化けしている
確認結果
case 1
case | case 1 |
---|---|
テストデータ(utf-8) | "20020307000020","album ","","2" |
結果 | OK |
0000000: 2232 3030 3230 3330 3730 3030 3032 3022 "20020307000020" 0000010: 2c22 616c 6275 6d20 2020 222c 2222 2c22 ,"album ",""," 0000020: 3222 0d0a 2"..
case 2
case | case 2 |
---|---|
テストデータ(utf-8) | "20020307000019","album ","生まれた!","2" |
結果 | NG |
0000000: 2232 3030 3230 3330 3730 3030 3031 3922 "20020307000019" 0000010: 2c22 616c 6275 6d20 2020 222c 22e7 949f ,"album ","... 0000020: e381 bee3 828c e381 9fef bc81 222c 2232 ............","2 0000030: 220d 0a "..
- 結果の詳細
- ij
ij> call SYSCS_UTIL.SYSCS_IMPORT_DATA('MW','TAGGED_MATERIAL',NULL,NULL,'C:/Users/kazyury/devel/ruby20/mwmig/case2.csv',',','"',NULL,1); エラー 38000: 式を評価している間に例外 'java.sql.SQLException: 列 'COLUMN4' は、FROM リスト内のどの表にもないか、結合仕様内にある一方でその結合仕様の範囲外であるか、または HAVING 文節内にある一方で GR OUP BY リストに入っていない可能性があります。 これが CREATE または ALTER TABLE ステートメントの場合、'COLUMN4' はターゲット表内の列ではありません。' がスローされました。 エラー 42X04: 列 'COLUMN4' は、FROM リスト内のどの表にもないか、結合仕様内にある一方でその結合仕様の範囲外であるか、または HAVING 文節内にある一方で GROUP BY リストに入っていない可能性があります。 こ れが CREATE または ALTER TABLE ステートメントの場合、'COLUMN4' はターゲット表内の列ではありません。
-
- eclipse Data Source Explorerからのロード
Loading "MW"."TAGGED_MATERIAL"... org.eclipse.datatools.sqltools.data.internal.core.load.DataFormatException: Unexpected token (found 2, expected ,) Data loading failed.
case 3
case | case 3 |
---|---|
テストデータ(utf-8) | "20020307000019","album ","生まれた","2" |
結果 | loadは成功。ただし、文字化け。 |
0000000: 2232 3030 3230 3330 3730 3030 3031 3922 "20020307000019" 0000010: 2c22 616c 6275 6d20 2020 222c 22e7 949f ,"album ","... 0000020: e381 bee3 828c e381 9f22 2c22 3222 0d0a .........","2"..
- 結果の詳細
問題の原因
case2(第4フィールドのバイト数は15byte)でインポートデータのtoken区切りが誤っていること、及びcase3(第4フィールドのバイト数は12byte)で文字化けしてしまっていることから、ijがutf-8ファイルであることを認識せずに、2byte系のCodesetとして認識している様子。
Parameters for the import proceduresによると、文字コードを指定しなければデフォルトではJVMのCodesetと同様となるらしい。
CODESET
http://db.apache.org/derby/docs/10.4/tools/rtoolsimport64241.html
Specifies the code set of the data in the input file. The code set name should be one of the Java-supported character encoding sets. Data is converted from the specified code set to the database code set (UTF-8). You can specify a NULL value to interpret the data file in the same code set as the JVM in which it is being executed. The CODESET parameter takes an input argument that is a VARCHAR (128) data type.
確かにEclipseのencodingはMS932としているので、これが原因の様子。
対処
Eclipse Data Source Explorer からのロードでは、文字コード指定は行えない。
面倒ではあるが、基本的には1回作業なのでijからデータロードを行うことにする。
(因みに上記の例ではSYSCS_UTL.SYSCS_IMPORT_DATAを使用したが、CSVの全列を表の全列に入れるので、SYSCS_UTL.SYSCS_IMPORT_TABLEで良い。引数も少なくて済むのでSYSCS_IMPORT_TABLEを使用することにする。)
インポートプロシージャのシンタックスはImporting data using the built-in proceduresを、利用可能なCodesetはCODESET values for import and export proceduresを参考にした(何れもhttp://db.apache.org/derby/docs/10.4以下のページ)。
C:\Program Files\Java\jdk1.7.0_13\db\bin>ij ij バージョン 10.8 ij> connect 'jdbc:derby:C:\Users\kazyury\MyDB'; Sat May 11 13:40:48 JST 2013 Thread[main,5,main] java.io.FileNotFoundException: derby.log (アクセスが拒否されました。) ---------------------------------------------------------------- Sat May 11 13:40:49 JST 2013: Derby バージョン The Apache Software Foundation - Apache Derby - 10.8.2.2 - (1181258): インスタンス a816c00e-013e-91e4-27a4-00000181c938 を クラスローダー sun.misc.Launcher$AppClassLoader@17f7be7b によってデータベースディレクトリ C:\Users\kazyury\MyDB 上でブート中 java.vendor=Oracle Corporation java.runtime.version=1.7.0_13-b20 user.dir=C:\Program Files\Java\jdk1.7.0_13\db\bin derby.system.home=null データベースクラスローダーが開始されました - derby.database.classpath='' ij> call SYSCS_UTIL.SYSCS_IMPORT_TABLE('MW','TAGGED_MATERIAL','C:/Users/kazyury/devel/ruby20/mwmig/case2.csv',',','"','UTF-8',1); 0 行が挿入/更新/削除されました ij> disconnect; ij> exit; ---------------------------------------------------------------- Sat May 11 13:42:55 JST 2013: Derby エンジンをシャットダウンしています ---------------------------------------------------------------- Sat May 11 13:42:55 JST 2013: クラスローダー sun.misc.Launcher$AppClassLoader@17f7be7b を持つデータベースディレクトリ C:\Users\kazyury\MyDB のインスタンス a816c00e-013e-91e4-27a4-00000181c938 をシャットダウンしています ---------------------------------------------------------------- C:\Program Files\Java\jdk1.7.0_13\db\bin>
LibreOfficeのBaseから確認
うむ、OKっぽい。