[英]dynamic table name in select statement
I have a series of history tables in an oracle 9 database. 我在oracle 9数据库中有一系列历史表。 History_table_00 contains last months data, History_table_01 contains the month before, and History_table_02 the month before that. History_table_00包含上个月的数据,History_table_01包含前一个月,History_table_02包含前一个月。 Next month, History_table_02 will automatically get renamed to history_table_03, history_table_01 renamed to history_table_02, history_table_00 renamed to history_table_01, and a new history_table_00 will be created to gather the newest history (I really hope I am making sense). 下个月,History_table_02将自动重命名为history_table_03,history_table_01重命名为history_table_02,history_table_00重命名为history_table_01,并且将创建新的history_table_00以收集最新的历史记录(我真的希望我有意义)。
Anyway, I need to write a select statement that will dynamically select all history tables. 无论如何,我需要编写一个select语句来动态选择所有历史表。 I am hoping this won't be too complicated because they all share the same name, just appended with sequential number so I can discover the table names with: 我希望这不会太复杂,因为它们都共享相同的名称,只是附加了序号,所以我可以发现表名:
select table_name from all_tables where table_name like 'HISTORY_TABLE_%';
My standard query for each table is going to be: 我对每个表的标准查询将是:
select id, name, data_column_1, data_column_2 from history_table_%;
What do I have to do to accomplish the goal of writing a sql statement that will always select from all history tables without me needing to go in every month and add the new table? 我需要做些什么来完成编写一个sql语句的目标,该语句总是从所有历史表中选择而不需要每个月都进入并添加新表? Thanks for anything you guys can provide. 感谢你们提供的任何东西。
you can use ref cursor but i wouldn't recommend it. 你可以使用ref游标,但我不推荐它。 it goes like this 它是这样的
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
I would suggest you to define a view in which you select from all history tables using union all
and each time the tables are renamed you modify the view as well. 我建议你定义一个视图,在这个视图中你可以使用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
;
then you can simle SELECT * FROM history_data; 然后你就可以看到SELECT * FROM history_data;
you can build the view dynamicaly with the help of the following statment: 您可以借助以下参数动态构建视图:
SELECT 'SELECT id, name, data_column_1, data_column_2 FROM ' || table_name || ' union all '
FROM user_tables
WHERE table_name like 'HISTORY_TABLE_%'
The best idea is to do a dynamic SQL statement that builds up a large query for each table existing in the database. 最好的想法是执行动态SQL语句,为数据库中现有的每个表构建一个大型查询。 Give the following SQL query try. 尝试以下SQL查询。 (please forgive my formatting, I am not sure how to do line-breaks on here) (请原谅我的格式,我不知道如何在此处进行换行)
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)
A Possible Solution: 可能的解决方案:
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:I dont have Oracle installed , so havent tested it for syntax errors. PS:我没有安装Oracle,所以没有测试它的语法错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.