我在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语句的目标,该语句将始终从所有历史记录表中选择,而不需要每个月都进入并添加新表?感谢你们提供的任何东西。
答案 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,所以没有测试它的语法错误。