从两个表中选择公共列
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 可以添加两个不同列的表吗?