如何 select 仅 pl/sql 中应截断的分区

How to select only the partitions that should be truncated in pl/sql

给定 2 个具有值的变量:
v_days1 = 30 v_days2 = 367

以及来自 ALL_TAB_PARTITIONS 的以下分区:

TABLE_NAME  PARTITION_NAME        HIGH_VALUE (LONG datatype)
TABLENAME   partitionname1_P30    30
TABLENAME   partitionname2_P60    60 
TABLENAME   partitionname3_P90    90
TABLENAME   partitionname4_P120   120
TABLENAME   partitionname5_P150   150
TABLENAME   partitionname6_P180   180 
TABLENAME   partitionname7_210    210
TABLENAME   partitionname8_P240   240
TABLENAME   partitionname9_P270   270
TABLENAME   partitionname10_P300  300
TABLENAME   partitionname11_P330  330
TABLENAME   partitionname12_P360  367

如何将all_tab_partitions中不等于v_days1v_days2的selectHIGH_VALUE截断对应的分区?

对于此示例,将分区 partitionname2_P60 截断为 partitionname11_P330

FOR rec IN (SELECT TABLE_NAME, PARTITION_NAME, HIGH_VALUE       
        FROM ALL_TAB_PARTITIONS 
        WHERE TABLE_NAME='TABLENAME'
        AND HIGH_VALUE NOT IN (v_days1, v_days2) LOOP

        <TRUNCATE PARTITIONS WITH HIGH_VALUE 60 TO 333 
        /TRUNCATE PARTITIONS WITH HIGH_VALUE NOT EQUAL TO 30 AND 367>

因为 high_value 数据类型是 Long 你不能直接在 where 子句中使用它。需要先隐蔽成lob才能使用。然而,在这种情况下,它变得难以使用,因为您必须在一个数字范围之间查找。因此,您可以稍微修改解决方案并实现您的要求,如下所示;

DECLARE
  v_days1 varchar2(10) := '20';
  v_days2 varchar2(10) := '367';
  l_var    VARCHAR2(32767);
  v_sql   VARCHAR2(100);
BEGIN
  FOR rec IN
  (SELECT table_name,
    partition_name,
    high_value
  FROM all_tab_partitions
  WHERE TABLE_NAME='TABLENAME'
 --WHERE high_value NOT IN  ( v_days1)
  )
  LOOP
    l_var:=rec.high_value;
    --dbms_output.put_line('partition Name'||rec.partition_name);

    --IF l_var between '20' and '367' THEN   
      IF (l_var NOT IN (v_days1 ,v_days2)) THEN  
      dbms_output.put_line('partition Name'||rec.partition_name);
      v_sql:= 'ALTER TABLE '||rec.table_name||' TRUNCATE PARTITION '||rec.partition_name ;

      EXECUTE immediate v_sql ;
   END IF;
  END LOOP;
END;