【问题标题】:Oracle : Drop multiple partitionsOracle:删除多个分区
【发布时间】:2015-11-13 15:57:23
【问题描述】:
一张表TMP有5个分区,分别是P_1、P_2、....P_5。
我需要删除一些 TMP 的分区;要删除的分区是由另一个查询派生的。
例如:
ALTER TABLE TMP DROP PARTITIONS (SELECT ... From ... //expression to get partition names )
假设 SELECT 语句返回 P_1 和 P_5。上面 ALTER 语句的部分查询不起作用。有什么方法可以删除来自 SELECT 语句的输入的分区?
【问题讨论】:
标签:
oracle
database-partitioning
partition
【解决方案1】:
您可以在anonymous pl/sql 块中使用dynamic sql;
Begin
for i in (select part_name from ... //expression to get partition names) loop
execute immediate 'ALTER TABLE TMP DROP PARTITION ' || i.part_name;
end loop;
end;
用于同时删除多个分区;
declare
v_part varchar(1000);
Begin
select LISTAGG(partition_name, ', ') WITHIN GROUP (ORDER BY partition_name DESC)
into v_part
from ... //expression to get partition names;
execute immediate 'ALTER TABLE TMP DROP PARTITION ' || v_part;
end;
【解决方案2】:
您需要使用动态 SQL。这个:
begin
for prec in (SELECT ... From ... //expression to get partition names )
loop
execute immediate 'ALTER TABLE TMP DROP PARTITION '
|| prec.partition_name;
end loop;
end;
/
显然,您需要完全相信您的查询将只返回您想要删除的分区。或者对您的备份和恢复计划有同等的信心:)
或者,您可以使用类似的方法生成一个放置脚本,您可以在运行之前对其进行查看。
【解决方案3】:
您必须使用 pl/sql 块通过选择查询从表中删除分区。使用 listagg 制作一个逗号分隔的列表。
DECLARE
var1 varchar2(50);
BEGIN
SELECT listagg(Partition_names) into var1 from table_name//expression to get partition names ;
execute immediate 'alter table tmp drop PARTITION'||var1 ;
END;
listagg 上的示例
select LISTAGG(partition_name,',') within group(order by table_name) as comma_list
from ALL_TAB_PARTITIONS where TABLE_owner='OWNER' AND TABLE_NAME='TABLE_NAME'
【解决方案4】:
您可以使用以下 sql 生成 DML 以删除多个表分区。
select 'ALTER TABLE ' || TABLE_OWNER || '.' || TABLE_NAME || ' DROP PARTITION ' || '"' || PARTITION_NAME || '";' from DBA_TAB_PARTITIONS
where TABLE_NAME='%YOUR_PATTERN%'order by PARTITION_NAME;
【解决方案5】:
也许有人可以帮忙。
此脚本删除特定架构的所有分区表的所有分区。我将它与带有 METADATA 的 clear DB 一起使用,用于更改已启动的(参考)分区。
ALTER TABLE SCHEMA_1.TABLE_1
SET INTERVAL ();
ALTER TABLE SCHEMA_1.TABLE_2
SET INTERVAL ();
ALTER TABLE SCHEMA_1.TABLE_3
SET INTERVAL ();
set lines 100
set heading off
spool runme.sql
select 'ALTER TABLE ' || TABLE_OWNER || '.' || TABLE_NAME || ' DROP PARTITION ' || '"' || PARTITION_NAME || '";' from DBA_TAB_PARTITIONS
where
TABLE_OWNER='SCHEMA_1'
-- and TABLE_NAME='TABLE_%'
and PARTITION_NAME LIKE 'SYS_P%'
;
@runme
ALTER TABLE SCHEMA_1.TABLE_1
SET INTERVAL (NUMTOYMINTERVAL(1,'MONTH'));
ALTER TABLE SCHEMA_1.TABLE_1
SET INTERVAL (NUMTOYMINTERVAL(1,'MONTH'));
ALTER TABLE SCHEMA_1.TABLE_3
SET INTERVAL (NUMTOYMINTERVAL(1,'MONTH'));
是的,脚本是半手动的,但我认为这样更安全。
ALTER TABLE ... INTERVAL 需要删除最后一个分区。
间隔必须与之前相同