【问题标题】:How to query data from a second table when the table's name is in first table's column data当表的名称在第一个表的列数据中时如何从第二个表中查询数据
【发布时间】:2016-09-06 14:37:27
【问题描述】:

我有一个奇怪的数据库架构(我无法更改),其中 TableA 中的行将包含一个存储更多信息的表名。我想从 TableA 中查询数据,并将它们与查询行中包含在表中的扩展值连接起来。

例如假设我有以下数据

TableA
Event ID     Accnt ID    DetailTable
-----------  ----------  ----------------
1            UserA       Table1
2            UserA       Table2
3            UserB       Table2

Table1
Accnt ID    Status
----------  ------------
UserA       Active

Table2
Accnt ID    Status
----------  ------------
UserA       Inactive
UserB       Active

我想要以下结果

select ... from ...

Result
Accnt ID   DetailTable    Status
---------  -------------  ---------
UserA      Table1         Active
UserA      Table2         Inactive
UserB      Table2         Active

这可能可以在 TableA 中的每条记录上使用循环然后查询正确的详细信息表来完成,但我想知道它是否可以在 Oracle SQL 中的单个 Select 语句中完成。

谢谢

【问题讨论】:

  • 动态 SQL 是要走的路。 (但似乎是一个非常奇怪的“问题”。)
  • 您不能将一个查询中的值用作同一查询中的 sql 关键字/标识符。不可能。您必须运行查询,获取值,然后使用该值构建一个新的 SQL 字符串,然后执行该字符串。
  • 动态 SQL 确实是要走的路。您可以使用流水线表函数,以便最终可以在简单的 sql 选择中使用它。看看oracle-base.com/articles/misc/pipelined-table-functions

标签: sql oracle


【解决方案1】:

这可能是一个常见问题,其中有人避免了 EAV 反模式并跳入了相反的反模式,即为存储在“主”表中的每种类型的对象动态生成详细信息表。当您发现自己将表或字段名称存储为数据时,可能是时候重新考虑您的架构了。但是,就像 EAV 一样,有时它是不可避免的。

如果您已经知道可能出现在 DetailTable 列中的表名,那么您可以有条件地加入这些表名,或者使用 UNION 查询(​​假设这些列在您的详细信息表中匹配得很好):

SELECT
    TableA.AccntID,
    unionDetail.DetailTable,
    unionDetail.Status
FROM
    TableA
    INNER JOIN 
        (
            SELECT AccntID, Status, 'Table1' as DetailTable FROM Table1
            UNION ALL
            SELECT AccntID, Status, 'Table2' FROM Table2        
        ) AS unionDetail ON
        TableA.AccntID = unionDetail.AccntID AND
        TableA.DetailTable = unionDetail.DetailTable

当然,如果明细表中的列不匹配,或者如果您有大量明细表或者它们被动态添加或删除,这一切都会崩溃。

【讨论】:

  • 这是一种有趣的方法,但现在我们有 60 个或更多详细信息表,最终将增长到 200 个或更多。幸运的是,列应该匹配,所以这是一个好的开始。谢谢。
  • 鉴于您的表名的通用性,我很害怕。我同意其他人的观点,在这种情况下,您需要通过 SP 或其他语言动态构建 SQL。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 2012-04-01
  • 2014-03-28
  • 2022-07-05
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多