2013-07-02 68 views
0

我在oracle 9数据库中有一系列的历史表。 History_table_00包含上个月的数据,History_table_01包含前一个月的数据,History_table_02包含前一个月的数据。下个月,History_table_02会自动重命名为history_table_03,history_table_01重命名为history_table_02,history_table_00重命名为history_table_01,并且将创建一个新的history_table_00以收集最新的历史记录(我真的很希望我有道理)。select语句中的动态表名

无论如何,我需要编写一个select语句来动态选择所有的历史表。我希望这不会是太复杂了,因为他们都有着相同的名字,只是顺序号附加这样我就可以发现与表名:

select table_name from all_tables where table_name like 'HISTORY_TABLE_%'; 

我对每个表的标准查询将是:

select id, name, data_column_1, data_column_2 from history_table_%; 

什么我必须做完成编写SQL语句,将始终从所有历史记录表中没有我选择需要去每个月并添加新表的目标是什么?感谢你们提供的任何东西。

+2

正确的解决方案是只有一个表格,并为'Year'添加一列作为主键的第一部分。 –

+1

@Joel Coehoorn--也许这是一个穷人的分区解决方案。你永远不会知道。 – haki

+0

@haki对主键的预计年份与大多数用例的单独表格具有相似的性能特征 –

回答

0

最好的办法是做一个动态的SQL语句,为数据库中现有的每个表建立一个大的查询。给出以下SQL查询尝试。 (请原谅我的格式,我不知道如何在这里做分行)

DECLARE @table VARCHAR(255) 
     , @objectID INT 
     , @selectQuery VARCHAR(MAX) 

SELECT @objectID = MIN(object_id) 
    FROM sys.tables 
WHERE name LIKE 'history_table_%' 

WHILE @objectID IS NOT NULL 
BEGIN 
    SELECT @table = name 
    FROM sys.tables 
    WHERE object_id = @objectID 
    ORDER BY object_id 

    SELECT @selectQuery = ISNULL(@selectQuery + ' UNION ALL ', '') + 'select id, name, data_column_1, data_column_2 FROM ' + @table 

    SELECT @objectID = MIN(object_id) 
    FROM sys.tables 
    WHERE name LIKE 'tblt%' 
    AND object_id > @objectID 
END 

SELECT @selectQuery 
--EXEC (@selectQuery) 
+0

感谢@SeanPrice,不知道我的解决方案是什么。我会给你一个旋转,看看。 – user1588433

2

你可以使用引用游标,但我不会推荐它。 它是这样的

create table tab_01 as select 1 a , 10 b from dual; 
create table tab_02 as select 2 a , 20 b from dual; 
create table tab_03 as select 3 a , 30 b from dual; 

create or replace function get_all_history 
return sys_refcursor 
as 
    r sys_refcursor; 
    stmt varchar2(32000); 
    cursor c_tables is 
      select table_name 
      from user_tables 
      where table_name like 'TAB_%'; 
begin 
    for x in c_tables loop 
      stmt := stmt || ' select * from ' || x.table_name ||' union all'; 
    end loop; 
    stmt := substr(stmt , 1 , length(stmt) - length('union all')); 
    open r for stmt; 
    return r; 
end; 
/

SQL> select get_all_history() from dual; 

GET_ALL_HISTORY() 
-------------------- 
CURSOR STATEMENT : 1 

CURSOR STATEMENT : 1 

     A   B 
---------- ---------- 
     1   10 
     2   20 
     3   30 
+0

感谢@haki。欣赏回应。 – user1588433

1

我建议你来定义你每次从表重命名你修改视图以及使用union all 所有历史记录表,并选择一个视图。

create OR replace view history_data as 
SELECT id, name, data_column_1, data_column_2 FROM history_table_01 
union all 
SELECT id, name, data_column_1, data_column_2 FROM history_table_02 
union all 
SELECT id, name, data_column_1, data_column_2 FROM history_table_03 
; 

然后你可以simle SELECT * FROM history_data;

就可以构建以下statment的帮助下查看dynamicaly:

SELECT 'SELECT id, name, data_column_1, data_column_2 FROM ' || table_name || ' union all ' 
FROM user_tables 
WHERE table_name like 'HISTORY_TABLE_%'  
+0

谢谢@schurik。但是,每个月都要手动进行修改视图正是我想要避免的。 – user1588433

+1

您如何重命名/创建表格?,您可以在该过程中集成创建意向表达。 – schurik

+0

这是一个很好的建议。我会把这个与拥有这个过程的人联系起来,看看他能做些什么。 – user1588433

0

一个可能的解决方案:

CREATE OR REPLACE PROCEDURE GET_HIST_DETAILS IS 

DECLARE 

QUERY_STATEMENT VARCHAR2(4000) := NULL; 
CNT    NUMBER; 

BEGIN 

select COUNT(table_name) INTO CNT from all_tables where table_name like 'HISTORY_TABLE_%'; 

FOR loop_counter IN 1..CNT 

LOOP 

IF LOOP_COUNTER <> CNT THEN 
{ 
QUERY_STATEMENT := QUERY_STATEMENT || 'select id, name, data_column_1, data_column_2 from history_table_0' || loop_counter || ' UNION'; 
} 
ELSE 
{ 
    QUERY_STATEMENT := QUERY_STATEMENT || 'select id, name, data_column_1, data_column_2 from history_table_0' || loop_counter ; 
} 

EXECUTE_IMMEDIATE QUERY_STATEMENT; 

END LOOP; 


END GET_DETAILS; 

PS:我没有安装了Oracle,所以还没有测试它的语法错误。