sql - 将数据类型 Clob 转换为 Varchar2 Oracle

标签 sql oracle type-conversion clob varchar2

我有一个 Oracle 表,其中有一列 clob 类型。我想保留列顺序并将数据类型更改为 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: invalid modification of columns

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

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

帮助将不胜感激。我已经为此工作了一段时间。如果您有任何疑问,请告诉我。

最佳答案

您可以删除 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

正如链接文档中提到的,您可以删除用于管理 rowids 的隐藏列:

alter table in_msg_board drop unused columns;

关于sql - 将数据类型 Clob 转换为 Varchar2 Oracle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30461697/

相关文章:

java - 如何查询 blob?

sql - 如何仅执行 SQL 文件中的选择性语句?

java - 在 Oracle ADF Faces 中获取表的渲染属性时出错

c++ - 显式 bool 运算符 - 无法返回、测试、初始化 bool

java - 在 Java 中将编译时常量 int 转换为编译时常量 String

sql - 如何将 SQL 文件导入 Rails 数据库?

sql - 更改序列以链接到另一个表

c++ - 指针和整数 C++ 之间的比较问题

php - 我想使用这个 for 循环清除数据库中的特定行值

Oracle 插入返回