В вашей процедуре есть синтаксические ошибки (например, 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'));
Обратите внимание, у вас также есть YEAR TO MONTH INTERVAL
в Oracle. Если вы хотите использовать это также, вы должны перегрузить процедуру, то есть создать вторую процедуру:
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
, см. Арифметика даты и времени / интервала