从两个表中选择公共列

Posted

技术标签:

【中文标题】从两个表中选择公共列【英文标题】:Select common columns from two tables 【发布时间】:2019-10-29 11:24:24 【问题描述】:

我有两张桌子

    temp_data_holder temp_data_holder1

这两个表会有一些共同的列,但它们也可以有一些额外的列,这些列可能只出现在一个表中。我需要一个从每个表中选择公共列的查询。

我可以使用以下查询获取常用列名

Select column_name 
from all_tab_columns 
where table_name like 'temp_data_holder' 
intersect 
Select column_name 
from all_tab_columns 
where table_name like 'temp_data_holder1';

有没有办法使用此查询从每个表中获取结果列?

我要求这样的东西

Select columns=(Select column_name from all_tab_columns where table_name like 'temp_data_holder' intersect Select column_name from all_tab_columns where table_name like 'temp_data_holder1') from temp_data_holder;

即表将在 for 循环内,每次迭代后结构都会改变,所以我不能简单地对列名进行硬编码

【问题讨论】:

您可以通过“动态 sql”(为另一个查询输出代码的查询)然后(对于 Oracle)使用 execute immediate 来实现这一点,有很多动态 sql 的示例可用 正如 Used_By_Already 所说:这称为动态 SQL。您执行查询以获取列名。然后使用此结果构建最终查询。你可以用几乎所有的编程语言来做到这一点。一种选择是在 DBMS 中使用 Oracle 的 PL/SQL,其他包括 Java、C#、php,......在您正在构建的某些应用程序或网站中。 那么你想怎么调用这段代码呢?如果投影随着每个循环而变化,则您需要可以动态处理 that 的东西。 无论如何,这是一个奇怪的请求。使用数据库表时,您应该确切地知道它们包含哪些列。可能是您对实际任务使用了错误的方法。 @Used_By_Already 谢谢,我使用动态 sql 查询完成了 【参考方案1】:

通常,您可以使用以下语句从两个表中获取公共列(按名称评估)。

 select listagg(column_name,',') within group (order by column_name)
    from (
      select column_name 
      from user_tab_columns 
      where table_name in (t1,t2) 
      group by column_name having count(*) = 2
    );

生成的字符串可用于生成有用的语句来比较两个表 t1 和 t2

【讨论】:

【参考方案2】:

SQL 和 PL/SQL 是强类型和严格的语言。即时做事很难。这使应用程序变得可靠,但受过自反性语言培训的开发人员却遇到了这种不灵活的情况。

也就是说,没有简单的方法可以实现您想要的。您需要将查询组装为字符串并使用动态 SQL 来执行完成的语句。您在读取结果集时也会遇到问题,因为 SQL 不处理临时投影。通常这意味着必须使用 Ref Cursor 从 Java 调用代码以映射到 JDBC ResultSet。

create or replace function get_data_for_common_cols return sys_refcursor is 

  stmt varchar2(32767) := 'select ';
  rc   sys_refcursor;

begin

  for recs in ( select t.column_name
                      , row_number() over (partition by t.table_name order by t.column_id) as rn
               from user_tab_columns t
                    join user_tab_columns t1 on t1.column_name = t.column_name
               where t.table_name  = 'TEMP_DATA_HOLDER' 
               and   t1.table_name = 'TEMP_DATA_HOLDER1' 
               order by t.column_id)
  loop
    if recs.rn != 1 then
      stmt := stmt || ',';
    end if;
    stmt := stmt || recs.column_name;
  end loop;

  stmt := stmt || ' from TEMP_DATA_HOLDER';

  open rc for stmt;

  return rc;

end;
/

这个函数可以被参数化为一个表名 - 或两个表名 - 用于循环查询和组装语句。这样做留给读者作为练习:)

【讨论】:

以上是关于从两个表中选择公共列的主要内容,如果未能解决你的问题,请参考以下文章

数据库:如何从具有一个公共列的两个表中获取多个值

IN SQL INNER JOIN 可以添加两个不同列的表吗?

HeidiSQL 根据两个条件从两个表中选择列

如何从 laravel 7 API 中的两个表中选择特定列?

如何使用公共列从多个表中检索数据

我想从两个表中选择某些列,并创建一个连接到第三个表