Oracle自动分区 - 分区的名称模式

时间:2017-01-03 12:39:46

标签: oracle oracle11g partitioning

我将使用Oracle 11g的自动分区,我想知道是否有任何选项可以提供分区名称特定模式?

例如我有:

create table 
pos_data ( 
   start_date        DATE,
   store_id          NUMBER,
   inventory_id      NUMBER(6),
   qty_sold          NUMBER(3),
) 
PARTITION BY RANGE (start_date) 
INTERVAL(NUMTOYMINTERVAL(1, 'MONTH')) 
(  
   PARTITION pos_data_init VALUES LESS THAN (TO_DATE('01-01-2017', 'DD-MM-YYYY')),
   PARTITION pos_data_201702 VALUES LESS THAN (TO_DATE('01-02-2017', 'DD-MM-YYYY')),
   PARTITION pos_data_201703 VALUES LESS THAN (TO_DATE('01-03-2017', 'DD-MM-YYYY')),
);

我将让init分区在2017年之前拥有所有行,然后是每个月的分区。

如何命名将自动生成的分区? 是否有机会创建名称末尾为YYYYMM的模式?或者我必须稍后重命名这些分区?

2 个答案:

答案 0 :(得分:5)

不,没有这样的选项允许您为动态创建的分区指定分区名称模式。如果出现这种需要,您可以/应该稍后重命名它们。我个人认为没有必要重命名它们。如果您想为这些自动生成的分区提供有意义的名称,以便您可以在查询中引用它们,例如:

select *
  from partitioned_table
  partition (part_1);

然后您可以轻松使用partition for (<<date>>)子句查询特定分区,这不需要您知道要查询的分区名称:

select *
  from partitioned_table
  partition for (date '2017-01-01')

答案 1 :(得分:1)

我使用此过程重命名由调度程序作业每天执行一次的分区:

FUNCTION DailyPartition(tableName IN VARCHAR2) RETURN BOOLEAN IS

    EXPRESSION_IS_OF_WRONG_TYPE EXCEPTION;
    PRAGMA EXCEPTION_INIT(EXPRESSION_IS_OF_WRONG_TYPE, -6550);

    ds INTERVAL DAY TO SECOND;
    ym INTERVAL YEAR TO MONTH;
    str VARCHAR2(1000);

BEGIN    
    SELECT INTERVAL INTO str 
    FROM USER_PART_TABLES 
    WHERE TABLE_NAME = tableName;

    EXECUTE IMMEDIATE 'BEGIN :ret := '||str||'; END;' USING OUT ym;
    RETURN FALSE;    
EXCEPTION 
    WHEN EXPRESSION_IS_OF_WRONG_TYPE THEN
        EXECUTE IMMEDIATE 'BEGIN :ret := '||str||'; END;' USING OUT ds;
        RETURN TRUE;    
END DailyPartition;


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 IN ('YOUR_TABLE', ...)
        AND PARTITION_NAME <> 'P_INITIAL'
    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;
        IF DailyPartition(aPart.TABLE_NAME) THEN            
            ts := ts - INTERVAL '1' DAY;
            newName := 'P_'||TO_CHAR(ts,'yyyy_mm_dd');
        ELSE
            ts := ADD_MONTHS(ts, -1);
            newName := 'P_'||TO_CHAR(ts,'yyyy_mm');
        END IF;
        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;