oracle 如何取消对表的分区并保留数据

zaq34kh6  于 2023-06-29  发布在  Oracle
关注(0)|答案(1)|浏览(228)

在一个Oracle 19 c数据库上,我正在迁移一个按范围分区的表,该表包含一堆按引用分区的详细信息表。由于一些遗留的复杂性,最简单的方法是取消对该表的分区,保留所有现有数据。我该怎么做?
我可以将所有现有的分区合并到一个分区中,但这仍然意味着表已分区(例如:我无法创建同名的新分区)。
这是我尝试的:
1.对具有未分区的临时表的主表使用DBMS_REDEFINITION。但是start_redef_table失败,并显示“ORA-23549:引用分区中涉及的表”
1.对详细信息表使用DBMS_REDEFINITION失败,并出现相同错误
1.删除细节表上的外键约束(这样我就可以在表上运行DBMS_REDEFINITION)。此操作失败,显示“ORA-14650:引用分区表不支持该操作”

ffscu2ro

ffscu2ro1#

有一个技巧你可以用途:交换分区!
要执行此操作:

  • 将所有分区合并为一个
  • 创建父表和子表的未分区空副本。从12.2开始,最好使用create table ... for exchange命令
  • 使用cascade选项将分区与新的父表交换。

所有的行都在未分区的表中。参见下面的示例。
dbms_redefinition不同,您需要复制约束、赠款等。数据也在新表中,因此您需要重命名它们/更新同义词/更改视图以使其对应用透明。

create table orders (
  order_id       int 
    primary key
    not null, 
  order_datetime date
    not null,
  customer_id    int 
    not null
) partition by range ( order_datetime )
  interval ( interval '1' month ) (
    partition p0 values less than ( date'2024-01-01' )
  );

create table order_items (
  order_id 
    constraint order_fk 
    references orders ( order_id ) 
    not null,
  product_id integer
    not null,
  primary key ( 
    order_id, product_id 
  ) 
) partition by reference ( order_fk );

insert into orders 
with rws as (
  select level x from dual
  connect by level <= 10
)
  select x, date'2023-01-01' + x, x
  from   rws;
  
insert into order_items
with rws as (
  select level x from dual
  connect by level <= 5
)
  select order_id, x
  from   orders cross join rws;

commit;

create table orders_stage
  for exchange with table orders;
  
create table order_items_stage
  for exchange with table order_items;

alter table order_items_stage
  add constraint order_items_pk_stage
  primary key ( order_id, product_id );  
  
alter table orders_stage
  add constraint order_pk_stage
  primary key ( order_id );  

alter table order_items_stage
  add constraint order_fk_stage
  foreign key ( order_id )
  references orders_stage ( order_id ) ;
  
alter table orders
  exchange partition p0
  with table orders_stage
  cascade;

select count(*) from orders_stage;    
/*
  COUNT(*)
----------
        10
*/
select count(*) from order_items_stage;
/*
  COUNT(*)
----------
        50
*/

相关问题