PROCEDURE purge_partitions
(
p_owner IN VARCHAR2
,p_name IN VARCHAR2
,p_retention_period IN NUMBER
) IS
BEGIN
FOR partition_rec IN (SELECT partition_name
,high_value
FROM dba_tab_partitions
WHERE table_owner = p_owner
AND table_name = p_name)
--drop partitions older than specified retention preriod
LOOP
IF SYSDATE >= add_months(to_date(substr(partition_rec.high_value
,12
,19)
,'YYYY-MM-DD HH24:MI:SS')
,p_retention_period)
THEN
execute_immediate('ALTER TABLE ' || p_owner || '.' ||
p_name || ' DROP PARTITION ' ||
partition_rec.partition_name);
END IF;
END LOOP;
END purge_partitions;
我正在尝试向循环语句添加更多的粒度,因此,我不仅希望每月删除分区,而且还要延长几天的时间。同样,仅供参考,记录是从Config标签中获取的,Config标签中包含分区表的详细信息(表所有者,名称和保留期-数据类型NUMBER)。因此,我不确定该如何进行。非常感谢您的帮助。
答案 0 :(得分:0)
恕我直言,列HIGH_VALUE的数据类型为LONG,因此在PL / SQL中很难使用。 但是无论如何您都不需要使用,而是有构造ALTER TABLE ... DROP PARTITION FOR (to_date(....)) 。因此,您根本不必处理生成的分区名称。
下面的示例从sales表中删除2007年9月的时间间隔分区。只有本地索引,因此没有索引无效。
ALTER TABLE sales DROP PARTITION FOR(TO_DATE('01-SEP-2007','dd-MON-yyyy'));
PS:该SQL扩展似乎已获得Oracle的专利。
答案 1 :(得分:0)
您的过程存在语法错误(例如execute_immediate(...)
)。
一个工作程序就是这个。您应该将其命名为drop_partitions
而不是purge_partitions
,因为您删除了这些分区。使用ALTER TABLE ... TRUNCATE PARTITION ...
,也可以进行“清除”:
CREATE OR REPLACE PROCEDURE drop_partitions(
p_owner IN VARCHAR2,
p_name IN VARCHAR2,
p_retention_period IN INTERVAL DAY TO SECOND) IS
ts TIMESTAMP;
CURSOR TabPartitions IS
SELECT partition_name, high_value
FROM dba_tab_partitions
WHERE table_owner = p_owner
AND table_name = p_name;
BEGIN
FOR partition_rec IN TabPartitions LOOP
EXECUTE IMMEDIATE 'BEGIN :ret := '||partition_rec.HIGH_VALUE||'; END;' USING OUT ts;
IF ts < SYSTIMESTAMP - p_retention_period THEN
--drop partitions older than specified retention preriod
EXECUTE IMMEDIATE 'ALTER TABLE ' || p_owner ||'.'||p_name
|| ' DROP PARTITION ' || partition_rec.partition_name || ' UPDATE GLOBAL INDEXES';
END IF;
END LOOP;
END drop_partitions;
然后您可以像这样调用该过程
purge_partitions('OWNER_NAME', 'TABLE_NAME', INTERVAL '60' DAY);
purge_partitions('OWNER_NAME', 'TABLE_NAME', NUMTODSINTERVAL(100, 'day'));
注意,您在Oracle中也有YEAR TO MONTH INTERVAL
。如果您也想使用此功能,则还必须重载该过程,即创建第二个过程:
CREATE OR REPLACE PROCEDURE drop_partitions(
p_owner IN VARCHAR2,
p_name IN VARCHAR2,
p_retention_period IN INTERVAL YEAR TO MONTH) IS
... rest would be exactly the same as above.
请注意,对于INTERVAL YEAR TO MONTH
,您会得到timestamp '2019-03-31 00:00:00' - INTERVAL '1' MONTH
之类的计算例外,请参阅Datetime/Interval Arithmetic