我将使用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的模式?或者我必须稍后重命名这些分区?
答案 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;