问题
A table TMP has 5 partitions, namely P_1, P_2,....P_5. I need to drop some partitions of TMP; the partitions to drop are derived by another query.
Ex:
ALTER TABLE TMP DROP PARTITIONS (SELECT ... From ... //expression to get partition names )
Let's say the SELECT statement returns P_1 & P_5. The part query of the ALTER statement above doesn't work. Is there any way to drop partitions with input from a SELECT statement?
回答1:
You can use dynamic sql
in anonymous pl/sql
block;
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;
For dropping multiple partitions on a go then;
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:
You'll need to use dynamic SQL. Something this:
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;
/
Clearly you need to have complete faith that your query will return only the partitions you want to drop. Or equivalent faith in your Backup & Recover plans :)
Alternatively you can use a similar approach to generate a drop script which you can review before you run it.
回答3:
You have to use pl/sql block for dropping partitions from a table with select query. Use listagg for making a comma separated list.
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;
Example on 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:
Maybe it's could somebody help.
This script drop all partitions for all partition tables for specific schema. I use it with clear DB with METADATA, for changing started (referencial) partition.
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'));
Yes, the script is semi-manual, but I think it's more safety.
ALTER TABLE ... INTERVAL
it's need for droping last partition.
Interval must be same that it was before
回答5:
You may use the following sql to generate DML for dropping multiple table partitions.
select 'ALTER TABLE ' || TABLE_OWNER || '.' || TABLE_NAME || ' DROP PARTITION ' || '"' || PARTITION_NAME || '";' from DBA_TAB_PARTITIONS
where TABLE_NAME='%YOUR_PATTERN%'order by PARTITION_NAME;
来源:https://stackoverflow.com/questions/32110948/oracle-drop-multiple-partitions