プログラマメモ2 - programmer no memo2

[oracle]varcharのデータ型にバイナリを入れることができるか。 2011/01/22

Oracleです。テーブルのデータ型で悩み中です。どういう悩みかというと、char,varchar2のデータ型にバイナリのデータ(ようするに生のデータ)を入るのか、というものです。本来は、そういう用途だと、BLOBとかRAWの型だというのは承知のうえで。

で、入れてそれを使えるのかという実験です。
もしかして、他に方法があるかもしれませんが、結論からいうとできないです。
>_<!

ちなみに環境は、プログラマメモ2: oracleオレオレ開発環境、まずは接続で使ったものと同じです。

NLS_CHARACTERSETは、


select * from nls_database_parameters where parameter ='NLS_CHARACTERSET';
NLS_CHARACTERSET
JA16SJISTILDE

です。

下記ようなテーブルを用意します。

create table aaa
(
code varchar(30),
moji1 varchar(10 BYTE),
moji2 varchar(10 BYTE),
moji3 raw(10),
moji4 blob
);

最初の列に文字コードを指定して、データとしてその文字コードで表現された文字を入れたいというような発想です。
列長セマンティックをよく知らず設定したりしてますが...

検証用コードです。

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class TestDB_moji {

public static void main(String[] args) throws SQLException,
ClassNotFoundException, IOException {
String s = "仲";
aaa("utf8", s);
aaa("sjis", s);
// aaa("jis", s);
}

/*
* 目的 VARCHARの項目にバイナリなデータを保存できるのかな検証
*
* シナリオ 文字コードを指定して,setBytesを使って登録し、とりだして復元できるか調べる
*/
static void aaa(String code, String s) throws SQLException,
IOException {
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.24.135:1521:test", "system",
"oracle");
// DatabaseMetaData meta = connection.getMetaData();

try {
if(true){
PreparedStatement statement = null;
String q = "INSERT INTO aaa(code, moji1, moji2, moji3, moji4) VALUES(?, ? , ?, ?, ?)";

statement = connection.prepareStatement(q);
// 文字コードで指定したバイト配列
byte[] bs = s.getBytes(code);
// まず普通に入れると
statement.setString(1, code);
statement.setString(2, new String(bs));// varchar2
statement.setBytes(3, bs);// varchar2
statement.setBytes(4, bs);// raw
statement.setBytes(5, bs);// blob
// statement.setBlob(5, new ByteArrayInputStream(bs));// blob
statement.executeUpdate();
connection.commit();
}
// バイトで値入れたら復元できるかな
{
ResultSet resultSet = null;

Statement statement = connection.createStatement();

resultSet = statement.executeQuery("select * from aaa");

int i = 0;
StringBuilder builder = new StringBuilder();
while (resultSet.next()) {
String c = resultSet.getString(1);
builder.append(
String.format(
"%d code:[%s] moi1:[%s] moi2:[%s] moi3:[%s] moi4:[%s]%n",
++i,
resultSet.getString(1), resultSet
.getString(2), new String(resultSet
.getBytes(3), c), new String(
resultSet.getBytes(4), c),
new String(resultSet.getBytes(5), c)));

}
resultSet.close();
statement.close();
System.out.println(builder);
Utils.write(new File("/z/a.txt"), new String(builder).getBytes());
}

} finally {
connection.close();
}

}
}

で、実行します。

こんな感じで登録されてます。


検証のプログラムの実行結果は、

1 code:[utf8] moi1:[莉イ] moi2:[E4BBB2] moi3:[仲] moi4:[仲]
2 code:[sjis] moi1:[仲] moi2:[9287] moi3:[仲] moi4:[仲]


raw,blobはjava側のgetBytesで復元できます。がvarcharでは復元できませんし、文字列になってしまってる...

: