Tuesday, October 12, 2010

RAW値の切り替え

ディクショナリーを検索してみるとRAWの形で提供されるコラムが時々あります。例えばUSER_TAB_COLSビューでコラムの最小値と最大値を見ると次のように意味の分からない変な値と見えます。

SQL> col column_name format a10
SQL> col data_type format a10
SQL> select
2 column_name,
3 data_type,
4 low_value,
5 high_value
6 from
7 user_tab_cols
8 where
9 table_name = 'T1'
10 ;

COLUMN_NAM DATA_TYPE LOW_VALUE HIGH_VALUE
---------- ---------- -------------------- --------------------
C1 NUMBER C102 C302
C2 VARCHAR2 6D616E79 6F6E65

このような値たちはUTL_RAW パッケージで切り替えられます。

SQL> select utl_raw.cast_to_number('C102') from dual;

UTL_RAW.CAST_TO_NUMBER('C102')
------------------------------
1

SQL> select utl_raw.cast_to_varchar2('6D616E79') from dual;

UTL_RAW.CAST_TO_VARCHAR2('6D616E79')
--------------------------------------------------------------------------------
many

次のように使用されるでしょう。

SQL> select
2 column_name,
3 data_type,
4 decode(data_type,
5 'NUMBER', utl_raw.cast_to_number(low_value)||'',
6 'VARCHAR2', utl_raw.cast_to_varchar2(low_value), low_value||'') as low_value,
7 decode(data_type,
8 'NUMBER', utl_raw.cast_to_number(high_value)||'',
9 'VARCHAR2', utl_raw.cast_to_varchar2(high_value), high_value||'') as high_value
10 from
11 user_tab_cols
12 where
13 table_name = 'T1'
14 ;

COLUMN_NAM DATA_TYPE LOW_VALUE HIGH_VALUE
---------- ---------- -------------------- --------------------
C1 NUMBER 1 10000
C2 VARCHAR2 many one

DBMS_STATS パッケージも同一な役割の関数を提供します。でも、パラメータの指定しかたが少し違います。使用の便利性のために次のように使用者定義関数を作ります。

SQL> -- dbms_stats (conversion)
SQL> create or replace function convert_me(p_value in raw, p_type in varchar2)
2 return varchar2
3 is
4 v_number number;
5 v_varchar2 varchar2(4000);
6 begin
7 if (p_type = 'NUMBER') then
8 dbms_stats.convert_raw_value(p_value, v_number);
9 return v_number|| '';
10 elsif (p_type = 'VARCHAR2') then
11 dbms_stats.convert_raw_value(p_value,v_varchar2);
12 return v_varchar2;
13 /* other data types */
14 else
15 return p_value || '';
16 end if;
17 end;
18 /

Function created.

SQL>
SQL> select convert_me('C102', 'NUMBER') from dual;

CONVERT_ME('C102','NUMBER')
--------------------------------------------------------------------------------
1

SQL> select convert_me('6D616E79', 'VARCHAR2') from dual;

CONVERT_ME('6D616E79','VARCHAR2')
--------------------------------------------------------------------------------
many

そうすると次のようにSQL文内で使用できます。

SQL> select
2 column_name,
3 data_type,
4 convert_me(low_value, data_type) as low_value,
5 convert_me(high_value, data_type) as high_value
6 from
7 user_tab_cols
8 where
9 table_name = 'T1'
10 ;

COLUMN_NAM DATA_TYPE LOW_VALUE HIGH_VALUE
---------- ---------- -------------------- --------------------
C1 NUMBER 1 10000
C2 VARCHAR2 many one

上のような面倒なことをしなくても良いようにOracleが自ら切り替えてくれたら良かったんですけどね。ともかく時折こんな切り替え作業が必要なところがあります。その際、活用すれば良いでしょう。

No comments:

Post a Comment