【问题标题】:one query for many similar tables一个查询许多相似的表
【发布时间】:2015-11-23 08:06:25
【问题描述】:

我有一个 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 语句可以运行,它从所有匹配的表名中提取到一个结果中,而不必显式地命名每个表。

类似

select * from table_%

这样的事情可能吗?如果不是,那么编写此查询的最有效方法是什么?

【问题讨论】:

  • Select * from table_% .. 不起作用。如果您不想自己编写查询。您可以在 sybObject 中搜索 table_% 之类的表,并通过一一解析来构建查询。
  • 是的,我知道我可以做到,但我希望有一个更优雅的解决方案。如果不可能有更优雅的东西,那么我将不得不采用某种我试图避免的循环。
  • 假设表的数量保持不变,您可以创建一个将所有表合并在一起的视图,然后查询该视图。但是,我不想保证 Oracle 在这种情况下是否能够推送谓词——您必须进行测试。另外,你需要结果是不同的吗?我很想使用 UNION ALL 而不是 UNION 创建视图,然后如果您确实需要结果是不同的,则在最终结果周围抛出一个不同的。
  • 不,在这种情况下,会不断添加和删除表,因此表数会发生变化。我调查了一个观点,但我认为问题仍然相似,不是吗?你仍然需要做一个很长的显式多表语句,我希望有一个更简单的方法。
  • 不,没有更简单的方法。您仍然需要在某个时候准确地告诉 Oracle 要查询哪些表。听起来像编写查询来编写查询是要走的路(正如@Ajay 建议的那样),除了您要查询的是 user_tables (或适当的 all_tables/dba_tables )。

标签: sql oracle union


【解决方案1】:

您可以使用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 的启发)。它是否有效(足够)是你需要用你的数据来测试的。

【讨论】:

  • 好的,所以说没有更简单的方法是错误的。虽然我不会完全称 XML 为“简单” *{;-)
  • 谢谢!甚至从不知道 Oracle 中存在这样的 XML 语法。
【解决方案2】:

这有点乱,最好在中间层执行,但我想你基本上可以遍历表并使用 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;

【讨论】:

  • 您可能需要建立一个字符串来对所有这些表进行联合/联合,然后使用它打开一个引用游标?否则,您必须选择所有这些单独的表格;我猜这可能是一个集合或 GTT。可能取决于 OP 需要如何使用结果。
【解决方案3】:

你可以写“select * from table_1 and table_2 and tabl_3;”

【讨论】:

  • 谢谢,但我澄清了我的问题,看看是否有办法写这个而不必明确命名每个表,因为我有数百个/
  • select * from table_1 and table_2 and tabl_3; 不是有效的 SQL!至少,不是在 Oracle 中!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 2021-06-02
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 2010-10-26
相关资源
最近更新 更多