2013-07-02 4 views
0

У меня есть серия таблиц истории в базе данных оракула 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

Правильное решение здесь состоит в том, чтобы иметь только одну таблицу и добавить столбец «Год» в качестве первой части первичного ключа. –

+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 
; 

тогда вы можете использовать SELECT * FROM history_data;

вы можете создать вид 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, поэтому нету протестировали его синтаксиса ошибки.