我有一个Oracle数据库,其中包含许多具有相同结构的表(列都完全相同)。表名也类似。表的名称类似于table_1,table_2,table_3 ......
我知道这不是最有效的设计,但我目前无法改变这一点。
在这种情况下,是否可以进行单个sql查询,在不明确使用确切表名的情况下,在多个表(数百个表)中提取具有相同条件的所有行?
我意识到我可以使用类似的东西 select * from table_1 UNION select * from table_2 UNION select * from table_3 ... select * from table_1000
但是是否有一个更优雅的sql语句可以运行,从所有匹配的表名中提取成一个结果,而不必显式地命名每个表。
像
这样的东西从表_%
中选择*这样的事情可能吗?如果没有,编写此查询的最有效方法是什么?
答案 0 :(得分: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 :(得分: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;
答案 2 :(得分:-3)
您可以在table_1和table_2以及tabl_3中编写"选择*;"