目的:打算把某个表改造成列表分区表,但列表值太多,有上千个,手工写分区表痛苦,经思考,想到此方法:
1 先创建只有DEFAULT类型的分区表,假设分区名为PART_DEF;
2 用脚本读取原表的列表值,然后对该分区表的分区PART_DEF劈开,新建该列表值的分区,如此循环,
直到结束。
--以下脚本,都在该表所在的数据库用户下执行
--1 使用该表所在的数据库用户登录SQLPLUS,执行下面的脚本
--1.1 设置建表语句的格式。
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'STORAGE',FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SEGMENT_ATTRIBUTES',FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'TABLESPACE',FALSE);
END;
/
--1.2 举例,获取要改造的表的建表语句。
set long 9999;
set pagesize 203;
select dbms_metadata.get_ddl('TABLE','T_CB_WIPDATAENTRY','') V_SQL from dual;
V_SQL
--------------------------------------------------------------------------------
CREATE TABLE "K3CLOUD"."T_CB_WIPDATAENTRY"
( "FENTRYID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FMAINID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FOWNERID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPRODUCTDIMEID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FCOSTCENTERID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPRODUCTTYPE" CHAR(1) DEFAULT '1' NOT NULL ENABLE,
"FPRODUCTID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERTYPE" VARCHAR2(20) DEFAULT ' ' NOT NULL ENABLE,
"FPROORDERID" VARCHAR2(36) DEFAULT ' ' NOT NULL ENABLE,
"FPROORDERSEQ" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERENTRYID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERNO" VARCHAR2(510) DEFAULT ' ' NOT NULL ENABLE,
"FWORKSHOPID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FBOMID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FLOTID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FAUXPROPID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FBASEUNITID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FWIPQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FREALWIPQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FDIFFQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FISAUTO" CHAR(1) DEFAULT '1' NOT NULL ENABLE,
"FINITADJQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FENDSTATUS" CHAR(1) DEFAULT '0' NOT NULL ENABLE,
"FPROORDERSTATUS" CHAR(1) DEFAULT '0' NOT NULL ENABLE,
"FMTONO" NVARCHAR2(255) DEFAULT ' ' NOT NULL ENABLE,
"FINITQTY" NUMBER(23,10) DEFAULT 0 NOTNULL ENABLE,
"FINPUTQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FFINISHQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
CONSTRAINT "PK_CB_WIPDATAENTRY" PRIMARY KEY ("FENTRYID") USING INDEX ENABLE )
Elapsed: 00:00:00.02
K3CLOUD@k3cloud>
--3 拷贝步骤2的表结构,改造成新的分区表。
CREATE TABLE "K3CLOUD"."T_CB_WIPDATAENTRY_20220214" --> 改表名
( "FENTRYID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FMAINID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FOWNERID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPRODUCTDIMEID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FCOSTCENTERID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPRODUCTTYPE" CHAR(1) DEFAULT '1' NOT NULL ENABLE,
"FPRODUCTID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERTYPE" VARCHAR2(20) DEFAULT ' ' NOT NULL ENABLE,
"FPROORDERID" VARCHAR2(36) DEFAULT ' ' NOT NULL ENABLE,
"FPROORDERSEQ" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERENTRYID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FPROORDERNO" VARCHAR2(510) DEFAULT ' ' NOT NULL ENABLE,
"FWORKSHOPID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FBOMID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FLOTID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FAUXPROPID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FBASEUNITID" NUMBER(10,0) DEFAULT 0 NOT NULL ENABLE,
"FWIPQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FREALWIPQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FDIFFQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FISAUTO" CHAR(1) DEFAULT '1' NOT NULL ENABLE,
"FINITADJQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FENDSTATUS" CHAR(1) DEFAULT '0' NOT NULL ENABLE,
"FPROORDERSTATUS" CHAR(1) DEFAULT '0' NOT NULL ENABLE,
"FMTONO" NVARCHAR2(255) DEFAULT ' ' NOT NULL ENABLE,
"FINITQTY" NUMBER(23,10) DEFAULT 0 NOTNULL ENABLE,
"FINPUTQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
"FFINISHQTY" NUMBER(23,10) DEFAULT 0 NOT NULL ENABLE,
CONSTRAINT "PK2_CB_WIPDATAENTRY" PRIMARY KEY ("FENTRYID") USING INDEX ENABLE ) --> 修改主键约束名
PARTITION BY LIST(FID) --> 新增分区信息
(PARTITION PART_DEF VALUES (default)) --> 新增默认分区信息
TABLESPACE K3CLOUD_DATA_TS; --> 指定分区表所在在表空间信息
--4 模拟语句案例
alter table t_cb_wipdataentry split partition part_def values ('1048576') into (partition "PART_1048576", partition part_def) update global indexes;
--5 关闭每个分区/索引分区 8M 大小的默认值。
--5.1
alter session set "_partition_large_extents"=false;
alter session set "_index_partition_large_extents"=false;
--5.2 按列表分区字段值,拆分新表的默认分区,
set serverout on;
declare
v_j number(7) := 0;
v_sql varchar2(300);
begin
for i in (select substr(trim(fid),1,25) fid from t_cb_wipdataentry group by substr(trim(fid),1,25) order by lengthb(fid) desc) loop
begin
v_sql := 'alter table t_cb_wipdataentry_20220214 split partition part_def values('''||i.fid||''')';
v_sql := v_sql||' into (partition "PART_'||i.fid||'", partition part_def) update global indexes';
dbms_output.put_line(v_sql);
--execute immediate v_sql; --> 确认 alter table 语句没问题后,注释掉dbms_output.put_line(v_sql); 恢复此语句:去掉前面的 --。
--/* --> 确认 alter table 语句没问题后,去掉前面的 --。
v_j := v_j + 1;
if v_j= 100 then
return;
end if;
--*/
exception when others then dbms_output.put_line(v_sql); end;
end loop;
end;
/
--5.3 对比两语句的查询结果,是不是一样?不一样就有问题了。
select count(partition_name) from user_tab_partitions where table_name='T_CB_WIPDATAENTRY_20220214';
select count(distinct fid)+1 from t_cb_wipdataentry;
--6 重定义表的过程
--6.1
exec dbms_redefinition.can_redef_table(user,'T_CB_WIPDATAENTRY');
--6.2
alter table t_cb_wipdataentry parallel 8;
--6.3
exec dbms_redefinition.start_redef_table(user,'T_CB_WIPDATAENTRY','T_CB_WIPDATAENTRY_20220214');
--6.4
set serverout on;
declare
retval number(5);
begin
dbms_redefinition.copy_table_dependents (user,'T_CB_WIPDATAENTRY','T_CB_WIPDATAENTRY_20220214',ignore_errors=>TRUE,num_errors=>retval);
dbms_output.put_line(retval);
end;
/
--6.5
exec dbms_redefinition.sync_interim_table(user,'T_CB_WIPDATAENTRY','T_CB_WIPDATAENTRY_20220214');
--6.6
--exec dbms_redefinition.abort_redef_table (user,'CT_OPE_SENDTRUCK','T_CB_WIPDATAENTRY_20220214');
--6.7
exec dbms_redefinition.finish_redef_table(user,'T_CB_WIPDATAENTRY','T_CB_WIPDATAENTRY_20220214');
--6.8
alter table t_cb_wipdataentry noparallel;
alter table t_cb_wipdataentry_20220214 parallel 8;
--6.9
alter table t_cb_wipdataentry enable row movement;
--6.10
exec dbms_stats.gather_table_stats(user,'T_CB_WIPDATAENTRY',degree=>8);
--7 对比两表的数据量,T_CB_WIPDATAENTRY新表,应该比,T_CB_WIPDATAENTRY_20220214老表多。
select count(*) from T_CB_WIPDATAENTRY union all select count(*) from T_CB_WIPDATAENTRY_20220214;
--8 确认没问题了,再删除老表的数据。
truncate table T_CB_WIPDATAENTRY_20220214;
推荐阅读