最近有个需求,需要把一张表的一个字段由number型改为varchar2型,由于表里已经存在数据,直接改会报错。而且开发那边说,这个表要一直可以访问,不能停应用。
我想到了在线重定义,之前我每次用它都是来把堆表转换为分区表的,没有做过这种字段类型转换。我在测试库上完整的测试了两次,很成功。重定义的过程中,表一直都可以
访问,不影响DML操作。而且整个过程中索引、约束、包都为可用状态。
需求:把表SUR_SURVEY的TARGET_ID字段,类型由number型改为varchar2(256);
以下是我的脚本,大家看看可不可以这样做。
一、 ---------------创建中间表SUR_SURVEY_TBD,注意此处的建表语句要通过dbms_metadata.get_ddl来获得后,做一些修改,表名改为SUR_SURVEY_TBD,TARGET_ID字段类
型改为varchar2(256)。这种方式的建表语句比较全,默认值啦,主键啦都包含在内。
CREATE TABLE SUR_SURVEY_TBD
( "ID" NUMBER(19,0) NOT NULL ENABLE,
"GMT_CREATE" DATE DEFAULT SYSDATE NOT NULL ENABLE,
"CREATOR" VARCHAR2(32) DEFAULT '[SYS]' NOT NULL ENABLE,
"GMT_MODIFIED" DATE DEFAULT SYSDATE NOT NULL ENABLE,
"MODIFIER" VARCHAR2(32) DEFAULT '[SYS]' NOT NULL ENABLE,
"IS_DELETED" CHAR(1) DEFAULT 'n' NOT NULL ENABLE,
"QT_SET_ID" NUMBER(12,0) NOT NULL ENABLE,
"TARGET_ID" VARCHAR2(256) NOT NULL ENABLE,
"TARGET_TYPE" VARCHAR2(128) NOT NULL ENABLE,
"TARGET_NAME" VARCHAR2(512),
"GMT_SURVEY" DATE,
"SUBMITTER" VARCHAR2(128),
"IS_FINISHED" CHAR(1) DEFAULT 0 NOT NULL ENABLE,
"CUR_PAGE_NO" NUMBER(4,0) NOT NULL ENABLE,
"ADMIN_ROLE" VARCHAR2(128),
"CUSTOMER_ID" VARCHAR2(128),
"NOTE_ID" VARCHAR2(128),
"SRV_ID" VARCHAR2(128),
"SERVICE_ID" VARCHAR2(128),
"COL1" VARCHAR2(255),
"COL2" VARCHAR2(255),
"COL3" NUMBER(8,0),
"COL4" DATE,
"MEMBER_ID" VARCHAR2(128),
CONSTRAINT "SUR_SURVEY_PK_TBD" PRIMARY KEY ("ID"));
二、 ------调用DBMS_REDEFINITION.CAN_REDEF_TABLE()过程,如果表不满足重定义的条件,将会报错并给出原因。
EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(USER, 'SUR_SURVEY', DBMS_REDEFINITION.CONS_USE_PK);
三、 ------调用DBMS_REDEFINITION.START_REDEF_TABLE()过程,并提供下列参数:被重定义的表的名称、中间表的名称、列的映射规则、重定义方法。注意红色字体部分是重点。
EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'SUR_SURVEY', 'SUR_SURVEY_TBD','ID ID, GMT_CREATE GMT_CREATE,CREATOR CREATOR,GMT_MODIFIED GMT_MODIFIED,MODIFIER MODIFIER,IS_DELETED IS_DELETED,QT_SET_ID QT_SET_ID,to_char(TARGET_ID) TARGET_ID,TARGET_TYPE TARGET_TYPE,TARGET_NAME TARGET_NAME,GMT_SURVEY GMT_SURVEY,SUBMITTER SUBMITTER,IS_FINISHED IS_FINISHED,CUR_PAGE_NO CUR_PAGE_NO,ADMIN_ROLE ADMIN_ROLE,CUSTOMER_ID CUSTOMER_ID,NOTE_ID NOTE_ID,SRV_ID SRV_ID,SERVICE_ID SERVICE_ID,COL1 COL1,COL2 COL2,COL3 COL3,COL4 COL4,MEMBER_ID MEMBER_ID', DBMS_REDEFINITION.CONS_USE_PK);
四、 -------在中间表上创建索引,也可以在步骤一来做,不过这样做的效率高点。因为步骤一创建了索引,步骤三的插入操作会变慢。
CREATE INDEX SUR_SURVEY_TID_IND_TBD ON SUR_SURVEY_TBD(TARGET_ID) TABLESPACE APOLLO_IND;
CREATE INDEX SUR_SURVEY_QSID_IND_TBD ON SUR_SURVEY_TBD(QT_SET_ID) TABLESPACE APOLLO_IND;
CREATE INDEX SUR_SURVEY_G_IND_TBD ON SUR_SURVEY_TBD(GMT_SURVEY) TABLESPACE APOLLO_IND;
CREATE INDEX SUR_SURVEY_CID_IND_TBD ON SUR_SURVEY_TBD(CUSTOMER_ID) TABLESPACE APOLLO_IND;
五、 -------如果操作期间对表T有大量DML操作,可以执行SYNC_INTERIM_TABLE来减少finsh_redef_table的锁表时间。
EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE(user,'SUR_SURVEY','SUR_SURVEY_TBD');
六、 -------执行DBMS_REDEFINITION.FINISH_REDEF_TABLE()过程完成表的重定义。
EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE(USER, 'SUR_SURVEY', 'SUR_SURVEY_TBD');
七、 ------确认转换成功,红色字体部分。
weixh@CRMG>desc SUR_SURVEY
Name Null? Type
----------------------------------------------------------------------------------- -------- --------------------------------------------------------
ID NOT NULL NUMBER(19)
GMT_CREATE NOT NULL DATE
CREATOR NOT NULL VARCHAR2(32)
GMT_MODIFIED NOT NULL DATE
MODIFIER NOT NULL VARCHAR2(32)
IS_DELETED NOT NULL CHAR(1)
QT_SET_ID NOT NULL NUMBER(12)
TARGET_ID NOT NULL VARCHAR2(256)
weixh@CRMG>SELECT COUNT(*) FROM SUR_SURVEY;
COUNT(*)
----------
5557401
八、 ------重新编译依赖对象
alter PROCEDURE SURVEY.PRO_SURVEY_REPORT compile;
alter SYNONYM SURVEY.SUR_SURVEY compile;
九、 -----删除中间表
drop table SUR_SURVEY_TBD;
十、 -------对索引进行重命名,这个步骤根据需要可以省略,不过这个过程非常快,一两秒就可以完事,提前把脚本准备好。
ALTER INDEX SUR_SURVEY_TID_IND_TBD RENAME TO SUR_SURVEY_TID_IND ;
ALTER INDEX SUR_SURVEY_QSID_IND_TBD RENAME TO SUR_SURVEY_QSID_IND;
ALTER INDEX SUR_SURVEY_G_IND_TBD RENAME TO SUR_SURVEY_GMTSURVEY_IND;
ALTER INDEX SUR_SURVEY_CID_IND_TBD RENAME TO SUR_SURVEY_CID_IND;
ALTER INDEX SUR_SURVEY_PK_TBD RENAME TO SUR_SURVEY_PK;
alter table SUR_SURVEY drop constraint SUR_SURVEY_PK_TBD cascade;
alter table SUR_SURVEY add constraint SUR_SURVEY_PK primary key (ID) using index;
重定义过程中如果有报错,采取如下操作取消:
weixh@CRMG>EXEC DBMS_REDEFINITION.ABORT_REDEF_TABLE(user,'SUR_SURVEY','SUR_SURVEY_TBD');
PL/SQL procedure successfully completed.
整个过程中,索引,约束都为可用状态,以下是我在各个阶段的查询输出。:
weixh@CRMG>select constraint_TYPE,constraint_NAME, STATUS from user_constraints where table_name='SUR_SURVEY' and owner='WEIXH';------------步骤三
CO CONSTRAINT_NAME STATUS
-- ------------------------------------------------------------ ----------------
C SYS_C0085198 ENABLED
C SYS_C0085199 ENABLED
C SYS_C0085200 ENABLED
C SYS_C0085201 ENABLED
C SYS_C0085202 ENABLED
C SYS_C0085203 ENABLED
C SYS_C0085204 ENABLED
C SYS_C0085205 ENABLED
C SYS_C0085206 ENABLED
C SYS_C0085207 ENABLED
C SYS_C0085208 ENABLED
P SUR_SURVEY_PK ENABLED
12 rows selected.
weixh@CRMG>select index_name ,status from user_indexes where table_name='SUR_SURVEY'; ------------步骤三
INDEX_NAME STATUS
------------------------------------------------------------ ----------------
SUR_SURVEY_PK VALID
SUR_SURVEY_QSID_IND VALID
SUR_SURVEY_TID_IND VALID
SUR_SURVEY_GMTSURVEY_IND VALID
SUR_SURVEY_CID_IND VALID
weixh@CRMG>select index_name ,status from user_indexes where table_name='SUR_SURVEY_TBD';-------步骤四
INDEX_NAME STATUS
------------------------------------------------------------ ----------------
SUR_SURVEY_PK_TBD VALID
SUR_SURVEY_TID_IND_TBD VALID
SUR_SURVEY_QSID_IND_TBD VALID
SUR_SURVEY_G_IND_TBD VALID
SUR_SURVEY_CID_IND_TBD VALID
weixh@CRMG>select constraint_TYPE,constraint_NAME, STATUS from user_constraints where table_name='SUR_SURVEY_TBD' and owner='WEIXH'; -------步骤四
CO CONSTRAINT_NAME STATUS
-- ------------------------------------------------------------ ----------------
C SYS_C0085210 ENABLED
C SYS_C0085211 ENABLED
C SYS_C0085212 ENABLED
C SYS_C0085213 ENABLED
C SYS_C0085214 ENABLED
C SYS_C0085215 ENABLED
C SYS_C0085216 ENABLED
C SYS_C0085217 ENABLED
C SYS_C0085218 ENABLED
C SYS_C0085219 ENABLED
C SYS_C0085220 ENABLED
P SUR_SURVEY_PK_TBD ENABLED
12 rows selected.
weixh@CRMG>select index_name ,status from user_indexes where table_name='SUR_SURVEY'; ------------步骤五
INDEX_NAME STATUS
------------------------------------------------------------ ----------------
SUR_SURVEY_PK VALID
SUR_SURVEY_QSID_IND VALID
SUR_SURVEY_TID_IND VALID
SUR_SURVEY_GMTSURVEY_IND VALID
SUR_SURVEY_CID_IND VALID
weixh@CRMG>select constraint_TYPE,constraint_NAME, STATUS from user_constraints where table_name='SUR_SURVEY' and owner='WEIXH'; ------------步骤五
CO CONSTRAINT_NAME STATUS
-- ------------------------------------------------------------ ----------------
C SYS_C0085198 ENABLED
C SYS_C0085199 ENABLED
C SYS_C0085200 ENABLED
C SYS_C0085201 ENABLED
C SYS_C0085202 ENABLED
C SYS_C0085203 ENABLED
C SYS_C0085204 ENABLED
C SYS_C0085205 ENABLED
C SYS_C0085206 ENABLED
C SYS_C0085207 ENABLED
C SYS_C0085208 ENABLED
P SUR_SURVEY_PK ENABLED
12 rows selected.
weixh@CRMG>select index_name ,status from user_indexes where table_name='SUR_SURVEY'; ------------步骤六
INDEX_NAME STATUS
------------------------------------------------------------ ----------------
SUR_SURVEY_PK_TBD VALID
SUR_SURVEY_TID_IND_TBD VALID
SUR_SURVEY_QSID_IND_TBD VALID
SUR_SURVEY_G_IND_TBD VALID
SUR_SURVEY_CID_IND_TBD VALID
weixh@CRMG>select constraint_TYPE,constraint_NAME, STATUS from user_constraints where table_name='SUR_SURVEY' and owner='WEIXH'; ------------步骤六
CO CONSTRAINT_NAME STATUS
-- ------------------------------------------------------------ ----------------
C SYS_C0085210 ENABLED
C SYS_C0085211 ENABLED
C SYS_C0085212 ENABLED
C SYS_C0085213 ENABLED
C SYS_C0085214 ENABLED
C SYS_C0085215 ENABLED
C SYS_C0085216 ENABLED
C SYS_C0085217 ENABLED
C SYS_C0085218 ENABLED
C SYS_C0085219 ENABLED
C SYS_C0085220 ENABLED
P SUR_SURVEY_PK_TBD ENABLED
12 rows selected.