SELECT SQLだけでLONG型をVARCHAR2型へ変換する事はできません。TO_CHAR()や、TO_LOB()ファンクションを使ってLONG型の変換を試みても以下のようなエラーとなります。
- ORA-00932: データ型が一致しません: CHARが予想されましたがLONGです。
- ORA-00932: データ型が一致しません: -が予想されましたがLONGです。
ではどうするか
LONGデータをTO_LOBファンクションで変換してCLOBカラムへINSERTします。そのCLOBをTO_CHARファンクションでVARCHAR型へ変換する。といったイレギュラーな方法をとらないと実現できません。以下リンクではインデックス対象カラムの表示を試みるもLONG型の扱いに限界を感じ途中であきらめていましたが、今回はなんとかやり切ってみます。
1.事前にLONG型をCLOB型へ変換するためのテーブルを用意する
DBA_IND_EXPRESSIONSビューのCOLUMN_EXPRESSIONカラムはLONGで定義されています。これをいったんCLOBで定義したカラムで新たなテーブルを作成する。
create table TAB_INF( INDEX_OWNER varchar2(30) ,INDEX_NAME varchar2(30) ,TABLE_OWNER varchar2(30) ,TABLE_NAME varchar2(30) ,COLUMN_EXPRESSION CLOB ,COLUMN_POSITION number );
2.TO_LOBファンクションを使ってLONG型データをCLOBへ変換しINSERT
不本意ですが、いったんCLOBのカラムへINSERTする事で変換ができました。
insert into tab_inf (INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,COLUMN_EXPRESSION,COLUMN_POSITION) select INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,TO_LOB(COLUMN_EXPRESSION),COLUMN_POSITION from DBA_IND_EXPRESSIONS t where t.INDEX_OWNER='SOONI' ;
上記insert文で使っているselect文ですが、こちら単体ではエラーが発生し動作しません。 『ORA-00932: データ型が一致しません: -が予想されましたがLONGです。 』が発生します。
SQL> select INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,TO_LOB(COLUMN_EXPRESSION),COLUMN_POSITION
2 from DBA_IND_EXPRESSIONS t
3 where t.INDEX_OWNER='SOONI'
4 ;
select INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,TO_LOB(COLUMN_EXPRESSION),COLUMN_POSITION
*
行1でエラーが発生しました。:
ORA-00932: データ型が一致しません: -が予想されましたがLONGです。
-- 以下の通りINSERTでは正常に動作します
SQL> insert into tab_inf
2 (INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,COLUMN_EXPRESSION,COLUMN_POSITION)
3 select INDEX_OWNER,INDEX_NAME,TABLE_OWNER,TABLE_NAME,TO_LOB(COLUMN_EXPRESSION),COLUMN_POSITION
4 from DBA_IND_EXPRESSIONS t
5 where t.INDEX_OWNER='SOONI'
6 ;
5行が作成されました。
SQL>
3.変換後のデータを出力する
CLOB型に変換したおかげでTO_CHARも使えますし、VARCHAR2カラムとのUNIONも可能になります。(当然VARCHAR2のサイズを超えると制限がでてきます)
select w.TABLE_OWNER,w.TABLE_NAME,w.INDEX_NAME ,LISTAGG(w.IND_COL||' '||w.DESCEND ,',') within group (order by w.COLUMN_POSITION ) ind_cols from ( select c.TABLE_OWNER,c.TABLE_NAME,c.INDEX_NAME,c.COLUMN_POSITION ,decode(to_char(t.COLUMN_EXPRESSION),null,c.COLUMN_NAME,to_char(t.COLUMN_EXPRESSION)) ind_col ,decode(c.DESCEND,'DESC',c.DESCEND,null) descend ,c.COLUMN_NAME,t.COLUMN_EXPRESSION from dba_ind_columns c left outer join tab_inf t on c.TABLE_OWNER = t.TABLE_OWNER and c.TABLE_NAME = t.TABLE_NAME and c.INDEX_NAME = t.INDEX_NAME and c.COLUMN_POSITION = t.COLUMN_POSITION where c.TABLE_OWNER='SOONI' and c.TABLE_NAME='MST_ADDRESS' order by c.TABLE_OWNER,c.TABLE_NAME,c.INDEX_NAME,c.COLUMN_POSITION ) w group by w.TABLE_OWNER,w.TABLE_NAME,w.INDEX_NAME ;
実行結果
SQL> select w.TABLE_OWNER,w.TABLE_NAME,w.INDEX_NAME
2 ,LISTAGG(w.IND_COL||' '||w.DESCEND ,',') within group (order by w.COLUMN_POSITION ) ind_cols
3 from
4 (
5 select c.TABLE_OWNER,c.TABLE_NAME,c.INDEX_NAME,c.COLUMN_POSITION
6 ,decode(to_char(t.COLUMN_EXPRESSION),null,c.COLUMN_NAME,to_char(t.COLUMN_EXPRESSION)) ind_col
7 ,decode(c.DESCEND,'DESC',c.DESCEND,null) descend
8 ,c.COLUMN_NAME,t.COLUMN_EXPRESSION
9 from dba_ind_columns c left outer join tab_inf t
10 on c.TABLE_OWNER = t.TABLE_OWNER
11 and c.TABLE_NAME = t.TABLE_NAME
12 and c.INDEX_NAME = t.INDEX_NAME
13 and c.COLUMN_POSITION = t.COLUMN_POSITION
14 where
15 c.TABLE_OWNER='SOONI' and c.TABLE_NAME='MST_ADDRESS'
16 order by c.TABLE_OWNER,c.TABLE_NAME,c.INDEX_NAME,c.COLUMN_POSITION
17 ) w
18* group by w.TABLE_OWNER,w.TABLE_NAME,w.INDEX_NAME;
TABLE_OWNER TABLE_NAME INDEX_NAME IND_COLS
______________ ______________ _____________________ _____________________________________________________________________
SOONI MST_ADDRESS PK_MST_ADDRESS OAZA_TOWN_CHOME_CODE
SOONI MST_ADDRESS IDX_MST_ADDRESS_01 CITY_NAME
SOONI MST_ADDRESS IDX_MST_ADDRESS_02 "OAZA_TOWN_CHOME_NAME" DESC
SOONI MST_ADDRESS IDX_MST_ADDRESS_03 TO_CHAR("LATITUDE") ,TO_CHAR("LONGITUDE") ,"PREFECTURES_NAME" DESC
SOONI MST_ADDRESS IDX_MST_ADDRESS_04 PREFECTURES_CODE ,"PREFECTURES_NAME" DESC
SQL>
なんとかLONG型に納まっていたデータをVARCHAR2型に合わせてUNIONする事ができました。