如何根据日期删除多个间隔分区?
How to drop multiple interval partitions based on date?
我有一个基于每日分区的table。
我可以使用以下查询删除分区
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
使用)您可能会从使用partition_extended_name语法中获益。
您不需要知道分区名称,您可以使用日期引用分区,例如
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;
/
您必须使用 execute immediate
,因为 ALTER TABLE
语句中的 DATE 必须是静态的。
生成并执行以下语句:
alter table INT_PART drop partition for (DATE'2018-09-01')
alter table INT_PART drop partition for (DATE'2018-08-31')
....
alter table INT_PART drop partition for (DATE'2018-08-19')
alter table INT_PART drop partition for (DATE'2018-08-18')
除了异常 ORA-14758
(我忽略 - 请参阅下面的注释)之外,您应该处理异常
ORA-02149: Specified partition does not exist
根据您的业务,这可能应该被忽略 - 这一天不存在分区(并且您永远不会使用分区字典元数据引用这一天)。
注意 要解决 ORA-14758 Last partition in the range section cannot be dropped
异常,您可以使用这个小技巧。
我创建了一个名为 P_MINVALUE
的 dummy 分区(没有范围),它扮演着间隔开始的角色,因此它永远不会被删除.
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') )
);
我有一个基于每日分区的table。
我可以使用以下查询删除分区
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
使用)您可能会从使用partition_extended_name语法中获益。
您不需要知道分区名称,您可以使用日期引用分区,例如
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;
/
您必须使用 execute immediate
,因为 ALTER TABLE
语句中的 DATE 必须是静态的。
生成并执行以下语句:
alter table INT_PART drop partition for (DATE'2018-09-01')
alter table INT_PART drop partition for (DATE'2018-08-31')
....
alter table INT_PART drop partition for (DATE'2018-08-19')
alter table INT_PART drop partition for (DATE'2018-08-18')
除了异常 ORA-14758
(我忽略 - 请参阅下面的注释)之外,您应该处理异常
ORA-02149: Specified partition does not exist
根据您的业务,这可能应该被忽略 - 这一天不存在分区(并且您永远不会使用分区字典元数据引用这一天)。
注意 要解决 ORA-14758 Last partition in the range section cannot be dropped
异常,您可以使用这个小技巧。
我创建了一个名为 P_MINVALUE
的 dummy 分区(没有范围),它扮演着间隔开始的角色,因此它永远不会被删除.
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') )
);