2

我在 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 table_name from all_tables where table_name like 'HISTORY_TABLE_%';

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

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

我必须做些什么来完成编写一个总是从所有历史表中选择的 sql 语句的目标,而我不需要每个月都进入并添加新表?感谢你们提供的任何东西。

4

4 回答 4

2

我建议您定义一个视图,您可以在其中使用从所有历史表中进行选择,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
;

然后你可以简单的 SELECT * FROM history_data;

您可以借助以下语句动态构建视图:

SELECT 'SELECT id, name, data_column_1, data_column_2  FROM ' || table_name || ' union all ' 
FROM  user_tables 
WHERE table_name like 'HISTORY_TABLE_%'     
于 2013-07-02T15:24:01.633 回答
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
于 2013-07-02T15:12:22.210 回答
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)
于 2013-07-02T15:09:56.493 回答
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,所以没有测试它的语法错误。

于 2013-07-02T19:03:39.490 回答