【REDEFINITION】使用在线重定义dbms_redefinition完成主键列类型的调整
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,在《【REDEFINITION】不可使用dbms_redefinition完成列类型的调整(ORA-42016)》文章中谈到,在修改主键列类型的时候因列类型不一致导致ORA-42016错误,无法完成在
千家信息网最后更新 2025年12月01日【REDEFINITION】使用在线重定义dbms_redefinition完成主键列类型的调整在《【REDEFINITION】不可使用dbms_redefinition完成列类型的调整(ORA-42016)》文章中谈到,在修改主键列类型的时候因列类型不一致导致ORA-42016错误,无法完成在线重定义。
这个问题可以利用dbms_redefinition.cons_use_rowid结合字符函数(to_char)辅助完成。
解决方案如下,供参考。
1.创建表T1,包含一个NUMBER类型的主键列
sec@ora10g> create table T1 (x NUMBER(19) primary key);
Table created.
sec@ora10g> insert into t1 select rownum from all_objects;
11944 rows created.
sec@ora10g> commit;
Commit complete.
sec@ora10g> desc t1;
Name Null? Type
--------------- -------- ------------------
X NOT NULL NUMBER(19)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
2.创建中间表T1,注意此时主键列的类型是VARCHAR2不是NUMBER类型
sec@ora10g> create table T2 (x varchar2(20) primary key);
Table created.
sec@ora10g> desc t2;
Name Null? Type
--------------- -------- ------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
0
3.保证在线重定义的顺利执行,授予用户所需要的权限。
sec@ora10g> conn / as sysdba
Connected.
sys@ora10g> grant EXECUTE_CATALOG_ROLE,CREATE ANY TABLE,ALTER ANY TABLE,DROP ANY TABLE,LOCK ANY TABLE,SELECT ANY TABLE to sec;
Grant succeeded.
4.使用rowid方式完成在线重定义
1)验证是否可以在线重定义
sec@ora10g> exec dbms_redefinition.can_redef_table('SEC','T1',dbms_redefinition.cons_use_rowid);
PL/SQL procedure successfully completed.
注释:此命令等同于下面的命令
sec@ora10g> exec dbms_redefinition.can_redef_table('SEC','T1',2);
2)看一下此时目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
------------------- -------- ---------------------
X NOT NULL NUMBER(19)
sec@ora10g> desc t2
Name Null? Type
------------------- -------- ---------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
0
结构和数据没有变化。
3)开始在线重定义
sec@ora10g> exec dbms_redefinition.start_redef_table('SEC','T1','T2','to_char(x) x', dbms_redefinition.cons_use_rowid);
PL/SQL procedure successfully completed.
注释:此命令等同于下面的命令
sec@ora10g> exec dbms_redefinition.start_redef_table('SEC','T1','T2','to_char(x) x', 2);
关于start_redef_table参数内容的表述请参考下面内容。
PROCEDURE START_REDEF_TABLE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
UNAME VARCHAR2 IN
ORIG_TABLE VARCHAR2 IN
INT_TABLE VARCHAR2 IN
COL_MAPPING VARCHAR2 IN DEFAULT
OPTIONS_FLAG BINARY_INTEGER IN DEFAULT
ORDERBY_COLS VARCHAR2 IN DEFAULT
PART_NAME VARCHAR2 IN DEFAULT
4)看一下此时目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
------------------- -------- ----------------------
X NOT NULL NUMBER(19)
sec@ora10g> desc t2
Name Null? Type
------------------- -------- ----------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
11944
此时结构没有变化,数据已经同步到中间表T2表中。
5)模拟目标表T1的事务(以删除为例)
sec@ora10g> delete from t1 where rownum<10000;
9999 rows deleted.
sec@ora10g> commit;
Commit complete.
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
11944
此时发现T1表中数据有变化,但是中间表T2是没有变化的。很好理解,这样可以保证系统的性能。
此时我们可以使用"dbms_redefinition.finish_redef_table"完成此次在线重定义过程。也可以使用"dbms_redefinition.sync_interim_table"先同步一次数据。
sec@ora10g> exec dbms_redefinition.sync_interim_table('SEC', 'T1', 'T2');
PL/SQL procedure successfully completed.
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
1945
可见,此时数据表T1和T2的内容又一次得到同步。
6)完成在线重定义
sec@ora10g> exec dbms_redefinition.finish_redef_table('SEC','T1','T2');
PL/SQL procedure successfully completed.
7)完成在线重定义之后我们再一次看一下目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
--------------------- -------- -------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> desc t2;
Name Null? Type
---------------------- -------- --------------------
X NOT NULL NUMBER(19)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
1945
OK,此时我们的目标已经达到,目标表T1的主键类型已经通过在线重定义方式从NUMBER类型修改成了VARCHAR2类型!
继续观察,中间表T2的X字段类型在重定义后变成了目标表的NUMBER类型。
既然重定义使命已完成,中间表T2便可以退出历史舞台,删除之。
sec@ora10g> drop table t2 purge;
Table dropped.
5.小结
在线重定义功能在保证系统高可用的前提下完成数据库调整带来了非常大的便利。
此文中描述的使用在线重定义修改主键类型的例子并不普遍,在线重定义功能主要还是集中在以下几个场景:
Online table redefinition enables you to:
* Modify the storage parameters of a table or cluster
* Move a table or cluster to a different tablespace in the same schema
* Add, modify, or drop one or more columns in a table or cluster
* Add or drop partitioning support (non-clustered tables only)
* Change partition structure
* Change physical properties of a single table partition, including moving it to a different tablespace in the same schema
* Change physical properties of a materialized view log or an Oracle Streams Advanced Queueing queue table
* Add support for parallel queries
* Re-create a table or cluster to reduce fragmentation
* Change the organization of a normal table (heap organized) to an index-organized table, or do the reverse.
* Convert a relational table into a table with object columns, or do the reverse.
* Convert an object table into a relational table or a table with object columns, or do the reverse.
参考链接:http://download.oracle.com/docs/ ... bles.htm#ADMIN01514
Good luck.
secooler
10.03.19
-- The End --
这个问题可以利用dbms_redefinition.cons_use_rowid结合字符函数(to_char)辅助完成。
解决方案如下,供参考。
1.创建表T1,包含一个NUMBER类型的主键列
sec@ora10g> create table T1 (x NUMBER(19) primary key);
Table created.
sec@ora10g> insert into t1 select rownum from all_objects;
11944 rows created.
sec@ora10g> commit;
Commit complete.
sec@ora10g> desc t1;
Name Null? Type
--------------- -------- ------------------
X NOT NULL NUMBER(19)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
2.创建中间表T1,注意此时主键列的类型是VARCHAR2不是NUMBER类型
sec@ora10g> create table T2 (x varchar2(20) primary key);
Table created.
sec@ora10g> desc t2;
Name Null? Type
--------------- -------- ------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
0
3.保证在线重定义的顺利执行,授予用户所需要的权限。
sec@ora10g> conn / as sysdba
Connected.
sys@ora10g> grant EXECUTE_CATALOG_ROLE,CREATE ANY TABLE,ALTER ANY TABLE,DROP ANY TABLE,LOCK ANY TABLE,SELECT ANY TABLE to sec;
Grant succeeded.
4.使用rowid方式完成在线重定义
1)验证是否可以在线重定义
sec@ora10g> exec dbms_redefinition.can_redef_table('SEC','T1',dbms_redefinition.cons_use_rowid);
PL/SQL procedure successfully completed.
注释:此命令等同于下面的命令
sec@ora10g> exec dbms_redefinition.can_redef_table('SEC','T1',2);
2)看一下此时目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
------------------- -------- ---------------------
X NOT NULL NUMBER(19)
sec@ora10g> desc t2
Name Null? Type
------------------- -------- ---------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
0
结构和数据没有变化。
3)开始在线重定义
sec@ora10g> exec dbms_redefinition.start_redef_table('SEC','T1','T2','to_char(x) x', dbms_redefinition.cons_use_rowid);
PL/SQL procedure successfully completed.
注释:此命令等同于下面的命令
sec@ora10g> exec dbms_redefinition.start_redef_table('SEC','T1','T2','to_char(x) x', 2);
关于start_redef_table参数内容的表述请参考下面内容。
PROCEDURE START_REDEF_TABLE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
UNAME VARCHAR2 IN
ORIG_TABLE VARCHAR2 IN
INT_TABLE VARCHAR2 IN
COL_MAPPING VARCHAR2 IN DEFAULT
OPTIONS_FLAG BINARY_INTEGER IN DEFAULT
ORDERBY_COLS VARCHAR2 IN DEFAULT
PART_NAME VARCHAR2 IN DEFAULT
4)看一下此时目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
------------------- -------- ----------------------
X NOT NULL NUMBER(19)
sec@ora10g> desc t2
Name Null? Type
------------------- -------- ----------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
11944
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
11944
此时结构没有变化,数据已经同步到中间表T2表中。
5)模拟目标表T1的事务(以删除为例)
sec@ora10g> delete from t1 where rownum<10000;
9999 rows deleted.
sec@ora10g> commit;
Commit complete.
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
11944
此时发现T1表中数据有变化,但是中间表T2是没有变化的。很好理解,这样可以保证系统的性能。
此时我们可以使用"dbms_redefinition.finish_redef_table"完成此次在线重定义过程。也可以使用"dbms_redefinition.sync_interim_table"先同步一次数据。
sec@ora10g> exec dbms_redefinition.sync_interim_table('SEC', 'T1', 'T2');
PL/SQL procedure successfully completed.
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
1945
可见,此时数据表T1和T2的内容又一次得到同步。
6)完成在线重定义
sec@ora10g> exec dbms_redefinition.finish_redef_table('SEC','T1','T2');
PL/SQL procedure successfully completed.
7)完成在线重定义之后我们再一次看一下目标表T1和中间表T2的结构和数据
sec@ora10g> desc t1;
Name Null? Type
--------------------- -------- -------------------
X NOT NULL VARCHAR2(20)
sec@ora10g> desc t2;
Name Null? Type
---------------------- -------- --------------------
X NOT NULL NUMBER(19)
sec@ora10g> select count(*) from t1;
COUNT(*)
----------
1945
sec@ora10g> select count(*) from t2;
COUNT(*)
----------
1945
OK,此时我们的目标已经达到,目标表T1的主键类型已经通过在线重定义方式从NUMBER类型修改成了VARCHAR2类型!
继续观察,中间表T2的X字段类型在重定义后变成了目标表的NUMBER类型。
既然重定义使命已完成,中间表T2便可以退出历史舞台,删除之。
sec@ora10g> drop table t2 purge;
Table dropped.
5.小结
在线重定义功能在保证系统高可用的前提下完成数据库调整带来了非常大的便利。
此文中描述的使用在线重定义修改主键类型的例子并不普遍,在线重定义功能主要还是集中在以下几个场景:
Online table redefinition enables you to:
* Modify the storage parameters of a table or cluster
* Move a table or cluster to a different tablespace in the same schema
* Add, modify, or drop one or more columns in a table or cluster
* Add or drop partitioning support (non-clustered tables only)
* Change partition structure
* Change physical properties of a single table partition, including moving it to a different tablespace in the same schema
* Change physical properties of a materialized view log or an Oracle Streams Advanced Queueing queue table
* Add support for parallel queries
* Re-create a table or cluster to reduce fragmentation
* Change the organization of a normal table (heap organized) to an index-organized table, or do the reverse.
* Convert a relational table into a table with object columns, or do the reverse.
* Convert an object table into a relational table or a table with object columns, or do the reverse.
参考链接:http://download.oracle.com/docs/ ... bles.htm#ADMIN01514
Good luck.
secooler
10.03.19
-- The End --
类型
在线
数据
目标
结构
命令
变化
内容
保证
参考
同步
调整
功能
方式
注释
系统
面的
一致
事务
使命
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
数据库文件操作
cs1.6服务器2017
请查看数据库服务是否开启
怀旧服什么服务器配置好
网络技术外包合同
服务器安全狗上不了网
武汉软件开发公司一般哪家好
联想服务器如何做raid
黑龙江网络安全专家名单
金灿荣讲网络技术
数据库导出方法
不存在虚拟机管理服务器
我的世界1.18的服务器
梦幻新诛仙再续前缘服务器
税务网络安全经验材料
软件开发人员有什么要求
数据库科学计数法转换
上海app软件开发有几家
江西计算机网络技术学校哪家好
网络安全管理办法模版
天津软件开发王涛
软件开发 参数
软件开发 cap
数盾网络安全研究院
大同软件开发应用范围
临沧上门回收服务器
孝感软件开发企业
广电网络技术员考试内容
sql数据库模糊查看
软件开发注册类图