Home > Software engineering >  automatic partition naming for range partitioning
automatic partition naming for range partitioning

Time:01-03

I have a table like this

CREATE TABLE DATA_AUDIT (
    id_col NUMBER(*,0) NOT NULL ENABLE,
    col_2 VARCHAR2(10) NOT NULL ENABLE,
    col_3 NUMBER(*,0) NOT NULL ENABLE,
    col_4 VARCHAR2(10) NOT NULL ENABLE,
    col_5 VARCHAR2(10) NOT NULL ENABLE,
    CREATED_AT TIMESTAMP (3) default current_timestamp ,
    CONSTRAINT DATA_AUDIT_PK PRIMARY KEY (col_2,col_3,col_4)
 USING INDEX  ENABLE
)
 partition by range (CREATED_AT)
(
   partition p2022_jan
   values less than (to_date('01-jan-2022')),
   partition p2022_feb
   values less than (to_date('01-feb-2022')),
   partition p2022_mar
   values less than (to_date('01-mar-2022'))
)

Here - in above example - i need to explicitly mention the name in DDL

I want to create new partition automatically for every month data How can i achieve it naming it automatically - i am ok with any random name of partition

I am using oracle - Oracle Database 19c Enterprise Edition Release 19.0.0.0

CodePudding user response:

Assume that the table only has the first partition(p2022_jan) and you'll add new partitions to the table every month, then firstly create a stored procedure such as

CREATE OR REPLACE PROCEDURE Pr_Add_Part_to_Data_Audit is
  v_ddl       VARCHAR2(32767);
  v_date      DATE := TO_DATE(TO_CHAR(sysdate,'yyyy-mm-')||'01','yyyy-mm-dd');  
BEGIN 
  v_ddl :='ALTER TABLE data_audit ADD PARTITION p'||TO_CHAR(v_date,'yyyy')||'_'||TO_CHAR(v_date,'mon')||' VALUES LESS THAN ('''||v_date||''')';
  EXECUTE IMMEDIATE v_ddl;
END;
/

then, call that from a scheduler at the beginning of the upcoming months such as

DECLARE
  v_job_name VARCHAR2(32) := 'jb_add_part_data';
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(job_name        => v_job_name,
                            job_type        => 'STORED_PROCEDURE',
                            job_action      => 'Pr_Add_Part_to_Data_Audit',
                            start_date      => TO_DATE('01-02-2021 01:00:10',
                                                       'DD-MM-YYYY HH24:MI:SS'),
                            repeat_interval => 'FREQ=MONTHLY; BYHOUR=1;',
                            auto_drop       => false,
                            comments        => 'Adds a new partition every month');

  DBMS_SCHEDULER.ENABLE(v_job_name);
END;
/  

CodePudding user response:

Instead of a RANGE partition I would suggest an INTERVAL partition:

CREATE TABLE DATA_AUDIT (
    id_col NUMBER(*,0) NOT NULL ENABLE,
    col_2 VARCHAR2(10) NOT NULL ENABLE,
    col_3 NUMBER(*,0) NOT NULL ENABLE,
    col_4 VARCHAR2(10) NOT NULL ENABLE,
    col_5 VARCHAR2(10) NOT NULL ENABLE,
    CREATED_AT TIMESTAMP (3) default current_timestamp ,
    CONSTRAINT DATA_AUDIT_PK PRIMARY KEY (col_2,col_3,col_4) USING INDEX  ENABLE
)
 partition by range (CREATED_AT) INTERVAL (INTERVAL '1' MONTH)
(PARTITION p2021_dec VALUES LESS THAN (TIMESTAMP '2022-01-01 00:00:00')); 

Then Oracle will create new partition automatically every months.

For renaming you can runs this procedure by daily scheduler job as proposed by Barbaros Özhan.

PROCEDURE RenamePartitions IS

    ts TIMESTAMP;
    newName VARCHAR2(30);

    CURSOR TabPartitions IS
    SELECT TABLE_NAME, PARTITION_NAME, HIGH_VALUE
    FROM USER_TAB_PARTITIONS 
    WHERE TABLE_NAME = 'DATA_AUDIT'
    ORDER BY 1,2;

BEGIN

    EXECUTE IMMEDIATE 'ALTER SESSION SET DDL_LOCK_TIMEOUT = 180';

    FOR aPart IN TabPartitions LOOP
        EXECUTE IMMEDIATE 'BEGIN :ret := '||aPart.HIGH_VALUE||'; END;' USING OUT ts;
        ts := ADD_MONTHS(ts, -1);
        newName := 'p'||TO_CHAR(ts,'yyyy_mon', 'NLS_DATE_LANGUAGE = american');
        IF aPart.PARTITION_NAME <> newName THEN             
            EXECUTE IMMEDIATE 'ALTER TABLE '||aPart.TABLE_NAME||' RENAME PARTITION '||aPart.PARTITION_NAME||' TO '||newName;
        END IF;
    END LOOP;

END RenamePartitions;

Or see a more generic one: Partition table rename automatically in ORACLE

  • Related