如何把普通表改造成多分区的列表分区表。原创
金蝶云社区-福寿双全
福寿双全
0人赞赏了该文章 135次浏览 未经作者许可,禁止转载编辑于2022年05月05日 17:34:24

目的:打算把某个表改造成列表分区表,但列表值太多,有上千个,手工写分区表痛苦,经思考,想到此方法:

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;



赞 0