select语句中的动态表名

时间:2013-07-02 14:47:23

标签: sql oracle dynamic dynamic-sql

我在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 个答案:

答案 0 :(得分:2)

你可以使用ref游标,但我不推荐它。 它就像这样

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

答案 1 :(得分: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_%'     

答案 2 :(得分: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)

答案 3 :(得分: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,所以没有测试它的语法错误。