【问题标题】:How to get date range partition names on a table between two dates (Given date range)如何在两个日期之间的表上获取日期范围分区名称(给定日期范围)
【发布时间】:2020-07-06 21:06:19
【问题描述】:

我是一名开发人员。在我的表中,我有一个日期范围分区。 我想获取为两个日期之间的表定义的分区名称。 我尝试了以下查询,它返回了表上的所有分区。

select * from USER_TAB_PARTITIONS WHERE TABLE_NAME = 'TABLE NAME' ORDER BY PARTITION_NAME;

我的要求是,我将传递两个日期作为输入,并且在这两个日期之间我想获取分区名称。 请提出查询。

【问题讨论】:

    标签: oracle oracle11g partitioning


    【解决方案1】:

    这不是很简单;主要障碍是user_tab_partitions.high_value 数据类型,即long,很难使用。通常你会得到

    ORA-00932:不一致的数据类型:预期 - 长了

    错误。

    不过,只需几个步骤,就可以完成。看看这个例子。

    创建一个分区表并在其中插入几行:

    SQL> CREATE TABLE test_part
      2  (
      3     datum  DATE,
      4     text   VARCHAR2 (10)
      5  )
      6  PARTITION BY RANGE (datum)
      7     INTERVAL ( NUMTODSINTERVAL (1, 'day') )
      8     (PARTITION p0 VALUES LESS THAN (TO_DATE ('01.01.2020', 'dd.mm.yyyy')));
    
    Table created.
    
    SQL> INSERT INTO test_part
      2     SELECT DATE '2015-08-15', 'Little' FROM DUAL
      3     UNION ALL
      4     SELECT DATE '2020-03-26', 'Foot' FROM DUAL;
    
    2 rows created.
    

    user_tab_partitions 说什么?

    SQL> SELECT table_name, partition_name, high_value
      2    FROM user_tab_partitions
      3   WHERE     table_name = 'TEST_PART';
    
    TABLE_NAME      PARTITION_NAME  HIGH_VALUE
    --------------- --------------- -----------------------------------
    TEST_PART       P0              TO_DATE(' 2020-01-01 00:00:00', 'SY
                                    YYY-MM-DD HH24:MI:SS', 'NLS_CALENDA
                                    R=GREGORIA
    
    TEST_PART       SYS_P63         TO_DATE(' 2020-03-27 00:00:00', 'SY
                                    YYY-MM-DD HH24:MI:SS', 'NLS_CALENDA
                                    R=GREGORIA
    

    因此,您需要从high_value 列中提取date 部分。第一步有点愚蠢——创建一个新表;基本上是 CTAS:

    SQL> CREATE TABLE temp_utp
      2  AS
      3     SELECT table_name, partition_name, TO_LOB (high_value) high_value
      4       FROM user_tab_partitions;
    
    Table created.
    

    为简单起见(在进一步的步骤中),我将基于该表创建一个视图,该视图将提取 date 值(第 5 行):

    SQL> CREATE OR REPLACE VIEW v_utp
      2  AS
      3     SELECT table_name,
      4            partition_name,
      5            TO_DATE (SUBSTR (high_value, 12, 10), 'rrrr-mm-dd') datum
      6       FROM temp_utp;
    
    View created.
    

    现在剩下的就简单了:

    SQL> SELECT *
      2    FROM v_utp
      3   WHERE datum < DATE '2020-02-15';
    
    TABLE_NAME      PARTITION_NAME  DATUM
    --------------- --------------- ----------
    TEST_PART       P0              2020-01-01
    
    SQL>
    

    好的,您将使用两个date 参数,然后在最终查询中导致between,但这很容易修改。

    这里的主要缺点是创建temp_utp 表的CTAS;您必须像在主表中添加新分区一样频繁地重新创建它。一种选择是以预定的方式进行,例如使用数据库作业(如果您不知道如何操作,请参阅dbms_job 和/或dbms_scheduler 文档),这将安排一个存储过程,然后使用动态SQL,即execute immediate 创建temp_utp。您不必重新创建视图 - 只要创建了新的 temp_utp 表,它就会生效。

    【讨论】:

    • 对Oracle来说很奇怪,好像TO_LOB一开始不起作用。但你的解决方案是完美的。
    【解决方案2】:

    我试图为同一问题找到解决方案,发现创建一个将高值转换为日期的函数可以正常工作,如下所示

     CREATE OR REPLACE FUNCTION get_high_value_date(p_partition_name IN VARCHAR2)
     RETURN DATE
     IS
        l_varchar_date VARCHAR2(4000);
        l_date DATE;
     BEGIN
        EXECUTE IMMEDIATE 'SELECT high_value FROM all_tab_partitions WHERE partition_name = :1 ' INTO l_varchar_date
        USING p_partition_name;
        
        EXECUTE IMMEDIATE 'SELECT '||l_varchar_date||' FROM dual' INTO l_date;
        
        RETURN l_date;
     EXCEPTION WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE ( 'Exc: '||SQLERRM );
        RETURN NULL;
     END;
    

    然后你可以用它来获取日期值

    SELECT get_high_value_date (partition_name) partition_date, partition_name
      FROM all_tab_partitions
     WHERE table_name = :table
    

    【讨论】:

      猜你喜欢
      • 2017-12-20
      • 1970-01-01
      • 1970-01-01
      • 2019-03-24
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 1970-01-01
      相关资源
      最近更新 更多