动态选择分区

时间:2014-03-12 16:04:49

标签: oracle oracle10g

我有一个包含几百个分区的表格,我通常对最新的35个分区感兴趣。

因此,我正在尝试创建可以动态访问这些视图的视图。即始终使用最新的情况。

查询:

  select PARTITION_NAME,
  PARTITION_POSITION,
  NUM_ROWS,
  AVG_ROW_LEN
  from all_tab_partitions
    where
    table_name = 'MY_TABLE'
    AND PARTITION_NAME <> 'P_LAST'
    AND PARTITION_POSITION < (SELECT MAX(PARTITION_POSITION) 
    FROM all_tab_partitions) - 35
    order by 2 DESC
    ;

似乎要回复我感兴趣的分区名称,但是,我没有设法使用它的结果来选择分区。 e.g:

CREATE OR REPLACE VIEW MY_VIIEW AS
WITH t AS ( [Above query] )
SELECT * FROM 
MY_TABLE PARTITION (SELECT /*+ FIRST_ROWS(1) */ PARTITION_NAME 
                    from t);

(不是实际视图,只是一个例子)

那我该怎么做?如何创建一个始终是最新分区的视图(&#34; MAX&#34; execpt)?

我正在使用Oracle 10g

感谢

5 个答案:

答案 0 :(得分:4)

您只能使用PL / SQL

create or replace package my_table_ is
  type t_records is table of my_table%rowtype;
  function getpart(c_parts sys_refcursor) return t_records pipelined;
end;

create or replace package body my_table_ is
  function getpart(c_parts sys_refcursor) return t_records pipelined is
  v_partition all_tab_partitions.partition_name%type;
  v_row my_table%rowtype;
  c_mytab sys_refcursor;
  begin
    loop
      fetch c_parts into v_partition;
      exit when c_parts%notfound;
      open c_mytab for 'select * from my_table partition ('||v_partition||')';
      loop
        fetch c_mytab into v_row;
        exit when c_mytab%notfound;
        pipe row (v_row);
      end loop;
    end loop;
  end;
end;

现在你可以

select * from table(my_table_.getpart(cursor(<QUERY_RETURNING_PARTITION_NAMES>)));

答案 1 :(得分:3)

您可以在每个语句中使用一批具有分区名称的union all语句来构造视图查询,例如

create view p as
select * from my_table partition (part1)
union all
select * from my_table partition (part1)
...
union all
select * from my_table partition (part35)

答案 2 :(得分:3)

好的......我不认为您可以使用分区名称,但您可以使用分区的起始值来选择与这些分区匹配的数据...

所以你看起来像这样:

SELECT * FROM my_table WHERE date_col > get_part_limit( 'my_table', 35 ):

其中date_col是您用于分区的列 - 而get_part_limit是您编写的存储函数,如下所示:

...
BEGIN
  SELECT high_value FROM all_tab_partitions
    INTO local_var
   WHERE table_name = parameter_name
     AND PARTITION_POSITION = MAX... - 35

  EXECUTE IMMEDIATE 'SELECT '||local_var||' FROM DUAL' INTO local_return_value;
  RETURN local_return_value;
END;

答案 3 :(得分:2)

分区设计为对数据透明,因此当您编写查询时,您根本不知道数据的存储方式。

我看到只有一种可能性命中特定分区:WHERE子句应该匹配最新(或最新5)分区的分区列的值。

接下来的问题是动态构建这个WHERE子句。您已经知道oracle词典中有大量信息。因此,您将阅读该内容并创建一个构造函数,以将元数据条件转换回SQL。

答案 4 :(得分:1)

irl我们做同样的事情并使用falco的解决方案。 这是我的代码:

create or replace function longToDate( myOwner varchar2,
                     mytable_name  in varchar2,
                     mypartition_name  in varchar2
                    ) return date
   as

cDate date;
cvar varchar2(1024);
rq   varchar2(1024);
infiniteValue EXCEPTION;
PRAGMA EXCEPTION_INIT(infiniteValue, -00904);
begin
  select high_value into cvar FROM dba_tab_partitions t where  t.table_owner=myOwner and table_name=mytable_name and partition_name=mypartition_name;

  rq:='select '||cvar||'  from dual';
  execute immediate rq into cDate;
  return cdate;

EXCEPTION
WHEN infiniteValue
then return'01 jan 3000';
when others
then return null;

end longToDate;

Ant视图是这样的

create or replace view last_35 as
with maxdate as
(select longToDate(p.table_owner,p.table_name,p.partition_name) mydate,
       rank()over(order by p.partition_position desc) mypos,
       p.* from all_tab_partitions p
where p.table_name='MY_TABLE'
)
select /*+full(a)*/* from MY_TABLE a, maxdate
where MY_TABLE.partition_name>maxdate.mydate
and maxdate.mypos=35