2015年5月9日土曜日

[Oracle12C]拡張データ型でVARCHAR2やRAWの最大長をより大きい値にする

Oracle12cからの新機能の拡張データ型を使用すると、VARCHAR2NVARCHAR2RAWの最大サイズが32,767バイトまで指定可能となります。

※以前のバージョンでは、文字列(VARCHAR2、NVARCHAR2)は4000、RAWは2000が最大サイズだったかと思います。

拡張データ型の使用方法

拡張データ型は初期化パラメータのMAX_STRING_SIZEにより設定します。

この初期化パラメータには、以下の2種類の設定値があります。設定値を拡張データ型(EXTENDED)に変更するとSTANDARDに戻すことはできないので注意が必要です。
EXTENDED
上限が32,767バイトになります
STANDARD
Oracle12cより前のバージョンと同じ仕様となります。デフォルトはこの値となります。

現在値の確認

SQL> show parameters max_string_size

NAME                                        TYPE       VALUE
------------------------------------ ----------- ------------------------------
max_string_size                      string      STANDARD

UPGRADEモードでデータベースを再起動

非CDBの場合には、以下の手順でデータベースを再起動します。
SQL> shutdown
SQL> startup UPGRADE

拡張データ型の有効化

altert systemで拡張データ型を使用できるようにします。
SQL> alter system set MAX_STRING_SIZE = EXTENDED;

System altered.

SQL> show parameters max_string_size

NAME                                        TYPE        VALUE
------------------------------------ ----------- ------------------------------
max_string_size                      string      EXTENDED

rdbms/admin/utl32k.sqlを実行し、ノーマルモードでデータベースを再起動します。

テーブルを作ってみる

以下のように、VARCHAR2の4000バイトを突破したカラムを定義できるようになります。
CREATE TABLE TEST_TABLE
(
    EXTENDED_VARCHAR VARCHAR2(32767) NOT NULL
)

作成したテーブルの定義を確認すると、指定した桁数のVARCAR2列が定義されている事がわかります。
SQL> desc test_table;
 Name                                                Null?  Type
 ----------------------------------------- -------- ----------------------------
 EXTENDED_VARCHAR                   NOT NULL VARCHAR2(32767)

データを登録してみる

以下のように4000バイトを超えるデータを挿入、参照できていることがわかります。
SQL> insert into test_table values (rpad('1', 32767, '1'));

1 row created.

SQL> select length(extended_varchar) from test_table;

LENGTH(EXTENDED_VARCHAR)
------------------------
     32767

JDBCで扱ってみる


メータデータからカラム定義を取得

以下のコードでメタデータの情報を出力してみます。
final ResultSet rs = metaData.getColumns(null, null, "TEST_TABLE", null);
while (rs.next()) {
    System.out.println("rs.getString(\"column_name\") = " + rs.getString("column_name"));
    System.out.println("rs.getInt(\"data_type\") = " + rs.getInt("data_type"));
    System.out.println("Types.VARCHAR = " + Types.VARCHAR);
    System.out.println("rs.getString(\"type_name\") = " + rs.getString("type_name"));
    System.out.println("rs.getInt(\"column_size\") = " + rs.getInt("column_size"));
}

実行結果は、以下のようになります。ドキュメントには、4000バイトを超えるデータは内部的にはCLOBのテクノロジを使用して格納するとあったけど、テーブル作った時のデータタイプなどが取得できています。
table.getString("column_name") = EXTENDED_VARCHAR
table.getInt("data_type") = 12
Types.VARCHAR = 12
table.getString("type_name") = VARCHAR2
table.getInt("column_size") = 32767

データを参照してみる

JDBC経由での参照は特に何かを意識する必要はなさそうです。
型マッピングもVARCHAR2と同じですね。(CLOBになってなくてよかったです。)
final Statement statement = connection.createStatement();
final ResultSet rs = statement.executeQuery("select * from TEST_TABLE");
if (rs.next()) {
    final Object object = rs.getObject(1);
    System.out.println("String? " + (object instanceof String));
    final String str = String.class.cast(object);
    System.out.println("str.length() = " + str.length());
}
//-------------------
// 実行結果
//-------------------
String? true
str.length() = 32767