将数据类型Clob转换为Varchar2 Oracle

时间:2015-05-26 14:40:01

标签: sql oracle type-conversion clob varchar2

我有一个带有clob类型列的Oracle表。我想保留列顺序并将数据类型更改为varchar2。该列只包含文字。

update IN_MSG_BOARD set MSG_TEXT = null;
alter table IN_MSG_BOARD modify MSG_TEXT long;
alter table IN_MSG_BOARD modify MSG_TEXT varchar2(4000);

我收到了标准信息:

  

ORA-22859:列的修改无效

我尝试将列设置为null,然后转换为char或long,然后转换为varchar2。但似乎没有任何效果。我宁愿不必复制表来更改一列。

我不想阅读内容。我想将列的数据类型从clob更改为varchar2。

非常感谢帮助。我一直在研究这个问题。如果您有任何问题,请告诉我。

2 个答案:

答案 0 :(得分:1)

您可以执行以下步骤:

1. alter table my_table add (new_column varchar2(4000));

2. update my_table set new_column = dbms_lob.substr(old_column,4000,1);

3. alter table my_table drop column old_column

答案 1 :(得分:0)

您可以删除CLOB列,添加varchar2列,然后修复'使用online table redefinition的列顺序;假设您使用的是支持该版本的版本,并且您有权使用DBMS_REDEFINITION包。具有主键的表的非常简单的演示:

create table in_msg_board(col1 number primary key, msg_text clob, col3 date);

如果您不想将数据保留在原始列中:

alter table IN_MSG_BOARD drop column msg_text;
alter table IN_MSG_BOARD add msg_text varchar2(4000);

如果您确实想要保留数据,那么它只需要两个额外的步骤,如下面的rowid版本所示。

创建一个重新定义表,其中包含所需顺序的列:

create table in_msg_board_redef(col1 number, msg_text varchar2(4000), col3 date);

并致电包裹:

BEGIN
  DBMS_REDEFINITION.START_REDEF_TABLE(
    uname => user,
    orig_table => 'IN_MSG_BOARD',
    int_table => 'IN_MSG_BOARD_REDEF',
    col_mapping => 'col1 col1, msg_text msg_text, col3 col3');
  DBMS_REDEFINITION.FINISH_REDEF_TABLE(uname => user,
    orig_table => 'IN_MSG_BOARD',
    int_table => 'IN_MSG_BOARD_REDEF');
END;
/

desc in_msg_board;

Name     Null Type           
-------- ---- -------------- 
COL1          NUMBER         
MSG_TEXT      VARCHAR2(4000) 
COL3          DATE           

文档中有更多关于检查表是否对重定义,处理依赖表(外键)等有效。

如果您的表没有主键,则通过传递附加选项标志you can use rowids。对于此演示,我也会保留数据。

create table in_msg_board(col1 number, msg_text clob, col3 date);
insert into in_msg_board values (1, 'This is a test', sysdate);
alter table IN_MSG_BOARD add msg_text_new varchar2(4000);
update IN_MSG_BOARD set msg_text_new = dbms_lob.substr(msg_text, 4000, 1);
alter table IN_MSG_BOARD drop column msg_text;
alter table IN_MSG_BOARD rename column msg_text_new to msg_text;

desc in_msg_board

Name     Null Type           
-------- ---- -------------- 
COL1          NUMBER         
COL3          DATE           
MSG_TEXT      VARCHAR2(4000) 

和以前一样,此时新列(此时包含数据)在那里,但位置错误。所以像以前一样重新定义,但使用DBMS_REDEFINITION.CONS_USE_ROWID标志:

create table in_msg_board_redef(col1 number, msg_text varchar2(4000), col3 date);

BEGIN
  DBMS_REDEFINITION.START_REDEF_TABLE(
    uname => user,
    orig_table => 'IN_MSG_BOARD',
    int_table => 'IN_MSG_BOARD_REDEF',
    col_mapping => 'col1 col1, msg_text msg_text, col3 col3',
    options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);
  DBMS_REDEFINITION.FINISH_REDEF_TABLE(uname => user,
    orig_table => 'IN_MSG_BOARD',
    int_table => 'IN_MSG_BOARD_REDEF');
END;
/

desc in_msg_board;

Name     Null Type           
-------- ---- -------------- 
COL1          NUMBER         
MSG_TEXT      VARCHAR2(4000) 
COL3          DATE           

数据也在那里:

select * from in_msg_board;

      COL1 MSG_TEXT             COL3    
---------- -------------------- ---------
         1 This is a test       27-MAY-15

如链接文档中所述,您可以删除用于管理rowid的隐藏列:

alter table in_msg_board drop unused columns;