Oracle 重命名自动生成的列表分区

Oracle renaming auto generated list paritions

我有几个实现自动列表分区的环境。

一些产品经理不喜欢正在生成的系统 GENERATED 分区名称,并希望通过更有意义的名称来引用该分区。

为了解决这些问题,我正在尝试创建一个程序,该程序将根据 high_value 重命名分区。在下面的示例中,我按州进行分区,因此我要生成的名称是 P_OHIO、P_IOWA..

在下面的过程中,我收到以下错误:

ORA-14048: 分区维护操作不能与其他操作组合 ORA-06512:

有人可以告诉我为什么会出现此错误以及如何纠正它。

在此先感谢您的帮助和专业知识。


CREATE TABLE T21  
(  
      seq_num NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
      num NUMBER(*,0),
      state   VARCHAR2(20)  
   )  
  SEGMENT CREATION DEFERRED
  PARTITION BY LIST (state) AUTOMATIC  
 (PARTITION P_CALIFORNIA VALUES ('CALIFORNIA')  
);


 insert into t21 (num, state)
        select
          level * round(dbms_random.value(1,50)),
          case round(dbms_random.value(1,50))
            when   1 then 'Alabama'
            when   2 then 'Alaska'
            when   3 then 'Arizona'
            when   4 then 'Arkansas'
            when   5 then 'California'
           when   6 then 'Colorado'
           when   7 then 'Connecticut'
           when   8 then 'Delaware'
           when   9 then 'Florida'
           when  10 then 'Georgia'
           when  11 then 'Hawaii'
          when  12 then 'Idaho'
          when  13 then 'Illinois'
           when  14 then 'Indiana'
           when  15 then 'Iowa'
          when  16 then 'Kansas'
          when  17 then 'Kentucky'
          when  18 then 'Louisiana'
          when  19 then 'Maine'
          when  20 then 'Maryland'
          when  21 then 'Massachusetts'
          when  22 then 'Michigan'
           when  23 then 'Minnesota'
           when  24 then 'Mississippi'
           when  25 then 'Missouri'
           when  26 then 'Montana'
           when  27 then 'Nebraska'
           when  28 then 'Nevada'
           when  29 then 'New Hampshire'
           when  30 then 'New Jersey'
           when  31 then 'New Mexico'
           when  32 then 'New York'
           when  33 then 'North Carolina'
           when  34 then 'North Dakota'
           when  35 then 'Ohio'
           when  36 then 'Oklahoma'
           when  37 then 'Oregon'
           when  38 then 'Pennsylvania'
          when  39 then 'Rhode Island'
           when  40 then 'South Carolina'
           when  41 then 'South Dakota'
           when  42 then 'Tennessee'
           when  43 then 'Texas'
           when  44 then 'Utah'
           when  45 then 'Vermont'
           when  46 then 'Virginia'
           when  47 then 'Washington'
          when  48 then 'West Virginia'
           when  49 then 'Wisconsin'
          when  50 then 'Wyoming'
         end
     from dual
      connect by level <= 100;


SELECT TABLE_NAME, PARTITION_NAME, HIGH_VALUE FROM USER_TAB_PARTITIONS WHERE TABLE_NAME ='T21';

CREATE OR REPLACE PROCEDURE RenameListPartitions
 IS  

    CURSOR PartTables IS
    SELECT TABLE_NAME
    FROM USER_PART_TABLES 
    WHERE PARTITIONING_TYPE = 'LIST' 
    ORDER BY TABLE_NAME;

    CURSOR TabParts(aTableName VARCHAR2) IS 
    SELECT PARTITION_NAME, HIGH_VALUE
    FROM USER_TAB_PARTITIONS
 WHERE regexp_like(partition_name,'^SYS_P[[:digit:]]{1,10}')  AND
 TABLE_NAME = aTableName AND
table_name not like 'BIN$%'
    ORDER BY PARTITION_POSITION;

  newPartName VARCHAR2(30);
 
BEGIN

    FOR aTab IN PartTables LOOP 
       
        FOR aPart IN TabParts(aTab.TABLE_NAME) LOOP    
execute immediate 'select ' || aPart.HIGH_VALUE || ' from dual' into newPartName;

            IF newPartName <> aPart.PARTITION_NAME THEN
                EXECUTE IMMEDIATE 'ALTER TABLE '||aTab.TABLE_NAME||' RENAME PARTITION '||aPart.PARTITION_NAME||' TO '||newPartName;
            END IF;             
        END LOOP;
    END LOOP;

END RenameListPartitions;
/

EXEC RenameListPartitions;

你的一些分区值有空格 - 比如 'New York' - 所以你需要引用分区的标识符:

EXECUTE IMMEDIATE 'ALTER TABLE '||aTab.TABLE_NAME
  ||' RENAME PARTITION '||aPart.PARTITION_NAME
  ||' TO "'||newPartName||'"';

db<>fiddle

当然,这意味着您以后在明确引用它们时也需要引用它们;比方说,用下划线替换空格并更改为大写可能会更好,这样你会得到 NEW_YORK:

EXECUTE IMMEDIATE 'ALTER TABLE '||aTab.TABLE_NAME
  ||' RENAME PARTITION '||aPart.PARTITION_NAME
  ||' TO '||upper(replace(newPartName,' ','_'));

db<>fiddle