Oracle 基于日期删除多个分区

Oracle 基于日期删除多个分区,oracle,partition,Oracle,Partition,我有一个基于每日分区的表 我可以使用下面的查询删除分区 ALTER TABLE MY_TABLE DROP PARTITION FOR(TO_DATE('19-DEC-2017','dd-MON-yyyy')) 如何在15天之前删除所有分区多个分区?您可以像这样使用PL/SQL DECLARE CANNOT_DROP_LAST_PARTITION EXCEPTION; PRAGMA EXCEPTION_INIT(CANNOT_DROP_LAST_PARTITION, -1475

我有一个基于每日分区的表

我可以使用下面的查询删除分区

ALTER TABLE MY_TABLE DROP PARTITION FOR(TO_DATE('19-DEC-2017','dd-MON-yyyy'))

如何在15天之前删除所有分区多个分区?

您可以像这样使用PL/SQL

DECLARE
    CANNOT_DROP_LAST_PARTITION EXCEPTION;
    PRAGMA EXCEPTION_INIT(CANNOT_DROP_LAST_PARTITION, -14758);

   ts TIMESTAMP;
BEGIN
   FOR aPart IN (SELECT PARTITION_NAME, HIGH_VALUE FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'MY_TABLE') LOOP
      EXECUTE IMMEDIATE 'BEGIN :ret := '||aPart.HIGH_VALUE||'; END;' USING OUT ts;
      IF ts < SYSTIMESTAMP - INTERVAL '15' DAY THEN
      BEGIN
         EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE DROP PARTITION '||aPart.PARTITION_NAME|| ' UPDATE GLOBAL INDEXES';
      EXCEPTION
            WHEN CANNOT_DROP_LAST_PARTITION THEN
                EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE SET INTERVAL ()';
                EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE DROP PARTITION '||aPart.PARTITION_NAME;
                EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE SET INTERVAL( INTERVAL ''1'' DAY )';            
      END;
      END IF;
   END LOOP;
END;
对于您可能基于异常ORA-14758使用的间隔分区表,您可以从使用语法中获益

您不需要知道分区名称,而是使用日期引用分区,例如

alter table INT_PART drop partition for (DATE'2018-09-01')
因此,要从当天开始删除最后15个分区,将执行以下循环:

declare
 v_sql VARCHAR2(4000);
begin
  for cur in (select  
                trunc(sysdate,'MM') - numtodsinterval(rownum - 1, 'day') my_month
              from dual connect by level <= 15) 
  loop
     v_sql := q'[alter table INT_PART drop partition for (DATE']'||
                 to_char(cur.my_month,'YYYY-MM-DD')||q'[')]';
     execute immediate v_sql;
  end loop;
end;
/
除了我忽略的异常ORA-14758之外,请参见下面的注释,您应该处理该异常

ORA-02149:指定的分区不存在

取决于您的业务,这一点可能应该被忽略-今天不存在分区,您将永远不会使用分区字典元数据引用今天的内容

注意:要解决ORA-14758范围部分的最后一个分区不能被删除的问题,您可以使用这个小技巧

我创建了一个虚拟分区,其中没有一个称为p_MINVALUE的扩展块,该扩展块在很久以前扮演了间隔开始的角色,因此它永远不会被删除

CREATE TABLE int_part
      (
     transaction_date TIMESTAMP not null,
     vc_pad VARCHAR2(100)
      )
     SEGMENT CREATION DEFERRED 
     PARTITION BY RANGE (transaction_date) INTERVAL (NUMTODSINTERVAL(1,'DAY'))
      (
     PARTITION P_MINVALUE  VALUES LESS THAN (TO_DATE('2000-01-01', 'YYYY-MM-DD') ) 
   );

可能重复的我理解基于名称的删除。我正在尝试检查是否有基于日期范围的替代方案。您也可以删除名称上的分区。ALTER TABLE sales DROP PARTITION sales_q1_2008、sales_q2_2008、sales_q3_2008、sales_q4_2008。我不认为有什么东西在约会range@XING-谢谢在表用户选项卡分区中,高值具有时间戳“2017-01-01 00:00:00”。那么,我必须做任何更改吗?为什么这是“BEGIN:ret:=”| | | parate.HIGH|u VALUE | |”;结束;'必修的?为什么我们不能直接使用parate.HIGH_VALUE?因为HIGH_VALUE是数据类型LONG,有很多限制。如果分开,则不能直接使用。高值<。。。或者从用户\u选项卡\u分区,其中高\u值<。。。我会失败的。我把它写在我的答案里。最后一个,即您必须手动删除的初始创建的分区。一旦删除了最后一个分区,您将不会再次收到错误。关于为什么我们不能直接使用spart.HIGH_VALUE?,这是因为此列在数据库中存储为LONG。因此,它是该时间戳的字符串表示,而不是时间戳本身Name@WernfriedDomscheit谢谢你指出这一点。我编辑了链接。奇特的方法是,它必须用下划线partition_extended_name编写,才能在Oracle文档中找到它。
CREATE TABLE int_part
      (
     transaction_date TIMESTAMP not null,
     vc_pad VARCHAR2(100)
      )
     SEGMENT CREATION DEFERRED 
     PARTITION BY RANGE (transaction_date) INTERVAL (NUMTODSINTERVAL(1,'DAY'))
      (
     PARTITION P_MINVALUE  VALUES LESS THAN (TO_DATE('2000-01-01', 'YYYY-MM-DD') ) 
   );