2015-08-28 3 views
0

У меня есть база данных Oracle со многими таблицами, которые имеют одинаковую структуру (столбцы все одинаковые). Имена таблиц аналогичны. Имена таблиц выглядят как table_1, table_2, table_3 ...один запрос для многих подобных таблиц

Я знаю, что это не самый эффективный дизайн, но в настоящее время у меня нет возможности изменить это.

В этом случае можно сделать один запрос sql, чтобы извлечь все строки с одним и тем же условием для нескольких таблиц (сотни таблиц) без явного использования точного имени таблицы?

Я понимаю, что я мог бы использовать что-то вроде выберите * из table_1 UNION выбрать * из table_2 UNION выбрать * из table_3 ... выберите * от table_1000

Но есть более элегантное заявление SQL, который может быть запущен, что извлекает из всех совпадающих имен таблиц в один результат, не указывая явно каждую таблицу.

Что-то вроде

выберите * от table_%

ли что-то подобное возможно? Если нет, то какой самый эффективный способ написать этот запрос?

+0

Выберите * из таблицы_% .. не будет работать. Если вы не хотите самостоятельно писать запрос. Вы можете выполнить поиск в sybObject для таблицы, например table_%, и построить запрос, разобрав их один за другим. – Ajay

+0

Да, я знаю, что могу это сделать, но я надеялся на более элегантное решение. Если что-то более изящное невозможно, тогда мне придется идти с каким-то циклом, который я пытаюсь избежать. – Jonjilla

+1

Предполагая, что количество таблиц остается статическим, вы можете создать представление, объединяющее все объединения таблиц, а затем запросить представление.Тем не менее, я не хотел бы ручаться за то, сможет ли Oracle ударить предикаты в этом случае - вам придется протестировать. Кроме того, вам нужно, чтобы результаты были отличными? У меня возникнет соблазн создать представление, используя UNION ALL, а не UNION, а затем бросая отчетливые результаты, если вам нужны разные результаты. – Boneist

ответ

3

Вы можете использовать dbms_xmlgen для запроса таблицы, используя шаблон, который генерирует документ XML как CLOB:

select dbms_xmlgen.getxml('select * from ' || table_name 
    || ' where some_col like ''%Test%''') as xml_clob 
from user_tables 
where table_name like 'TABLE_%'; 

Вы сказали, что вы хотели состояние, так что я 'включил фиктивный, where some_col like '%Test%'.

Вы можете затем использовать XMLTable для извлечения значения обратно в виде реляционных данных, преобразование CLOB в XmlType на пути:

select x.* 
from (
    select xmltype(dbms_xmlgen.getxml('select * from ' || table_name 
    || ' where some_col like ''%Test%''')) as xml 
    from user_tables 
    where table_name like 'TABLE_%' 
) t 
cross join xmltable('/ROWSET/ROW' 
    passing t.xml 
    columns id number path 'ID', 
    some_col varchar2(10) path 'SOME_COL' 
) x; 

SQL Fiddle demo который извлекает одну строку соответствий от каждого из двух аналогичных таблиц. Конечно, это предполагает, что ваши имена таблиц следуют полезному шаблону, например table_%, но вы предлагаете, чтобы они это сделали.

Это единственный способ, которым я знаю сделать что-то подобное, не прибегая к PL/SQL (и, немного искавшись, возможно, был вдохновлен by this answer to count multiple tables). Насколько это эффективно (достаточно) - это то, что вам нужно будет проверить с вашими данными.

+1

Итак, я был неправ, чтобы сказать, что не было более простого способа. Хотя я бы точно не назвал XML «простым» * {;-) – Boneist

+0

Спасибо! Никогда даже не знал, что такой синтаксис XML существует в Oracle. – Jonjilla

-3

Вы можете написать «select * from table_1 и table_2 и tabl_3;»

+0

спасибо, но я уточнил свой вопрос, чтобы увидеть, есть ли что-нибудь, чтобы написать это, не имея явным образом называю каждую таблицу, так как у меня есть сотни из них/ – Jonjilla

+0

О, я знаю. Вы должны узнать больше SQL. –

+1

'select * from table_1 и table_2 и tabl_3;' недействителен SQL, хотя! По крайней мере, не в Oracle! – Boneist

0

Это своего рода беспорядок и лучше всего выполняется в среднем ярусе, но я полагаю, вы могли бы в основном перебирать таблицы и использовать EXECUTE IMMEDIATE, чтобы сделать это.

Что-то вроде:

for t in (select table_name from all_tables where table_name like 'table_%') loop 
    execute immediate 'select blah from ' || t.table_name; 
end loop; 
+0

Возможно, вам понадобится создать строку, которая объединяет/объединяет все эти таблицы, а затем, может быть, открыть курсор с помощью этого? В противном случае вам нужно выбрать все эти отдельные таблицы; который может быть сборником или GTT, я думаю. Зависит от того, как OP должен использовать результат, возможно. –

Смежные вопросы