使用 SQL 或 PL/SQL 对多个表中的列和表名进行动态查询
Posted
技术标签:
【中文标题】使用 SQL 或 PL/SQL 对多个表中的列和表名进行动态查询【英文标题】:Dynamic query with columns and table names from multiple tables using SQL or PL/SQL 【发布时间】:2015-04-18 11:16:46 【问题描述】:假设(为简单起见)我有两个表:
Product
product_id
CreatedDate
LastEditedBy
EditedDate
Entity
entity_id
CreatedDate
LastEditedBy
EditedDate
两个表具有相同的列名,但只有 ID 列具有不同的名称。我想运行一个查询,这样当我从 SQL plus 运行它时,我只需给它一个参数,它就会从其中一个表中获取数据。在上面的示例中,我可以像这样运行查询
@archiveHistory.sql product
@archiveHistory.sql entity
这是我的尝试,但它总是无法识别其中一列,即如果我使用产品运行它,它会说 entity_id 不存在。如果我用实体运行它,它说 product_id 不存在。
请注意,我在列选择和表名选择中都使用了传入的参数。
define identifier = '&1'
Select * from (
Select case lower('&identifier')
when product then product_id
when entity then entity_id
end ID, CreatedDate, LastEditedBy, EditedDate
From &identifier
)
如果 CASE 语句中的列列表都来自同一个表,我认为它会起作用。
问题
我需要做什么才能让查询忽略不相关的列,即如果参数是实体,则忽略 product_id
我考虑过使用匿名 PL/SQL 块(即 Begin End),但我不确定如何在不使用 dbms_output.put_line 的情况下显示输出。
【问题讨论】:
【参考方案1】:对于这种特殊情况,我认为以下纯 SQL 解决方案可能效果最好:
SELECT product_id AS the_field
, CreatedDate, LastEditedBy, EditedDate
FROM Product
WHERE LOWER('&identifier') = 'product'
UNION ALL
SELECT entity_id AS the_field
, CreatedDate, LastEditedBy, EditedDate
FROM Entity
WHERE LOWER('&identifier') = 'entity'
查询计划器将预先评估您的 '&identifier' = ...
谓词,从而防止执行不需要的联合子查询。
如果这不是一个选项(因为您的实际用例要复杂得多),Stack Overflow 上已经有很多关于从 PL/SQL 执行动态 SQL 的答案:
Executing a dynamic sql statement into a SYS_REFCURSOR Cursor For Loop with dynamic SQL-Statement Binding Parameters to Oracle Dynamic SQL您可以使用动态 SQL 将数据插入到临时表中,然后只需 SELECT * FROM temp_table
【讨论】:
OP 说我们应该假设他们有两个表“为简单起见”。我怀疑在现实生活中他们还有更多。 @APC:我同意,我从 "对于这个特殊情况" :-) 开始,但如果不存在该免责声明(“为简单起见” ),这将是一个更通用的问题的有用答案,人们在谷歌搜索此类主题时会找到该问题。因此,即使它可能对 OP 没有用,它也可能对其他人有用。以上是关于使用 SQL 或 PL/SQL 对多个表中的列和表名进行动态查询的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL 使用一张表中的列数据更新表,基于不同表之间的相等性
Oracle PL / SQL触发器,在UPDATE之前/之后仅用于识别表中已修改的列