我在oracle中有一个表,有10列,比如表A,有col_1,col_2,col_3等。我有另一个表B,表B中的行有表A中的列名co1_1,col_2,col_3。表B中的行可以不一样。
TABLE A
COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8 COL9 COL10
TABLE B
COL1
COL2
COL3
我想写一个oracle sql查询,根据表B中的列名(行)动态地获取选择列名。
如果表B中有3条记录有相应的列名,那么我的查询应该是这样的。
从A中选择col_1, col_2, col_3。
如果表B有4条记录,那么我的查询应该动态地改变为下面的内容。
select col_1, col_2, col_3, col_4 from A
你需要使用动态查询。
'SELECT '
|| (SELECT LISTAGG(COLNAME, ',') WITHIN GROUP (ORDER BY COLNAME) FROM TABLEB)
|| ' FROM TABLEA'
我认为我们应该到ALL_TAB_COLUMNS表中查找列名,像这样。
SELECT
'SELECT '
||
(SELECT LISTAGG( y.COLNAME, ',') WITHIN GROUP (ORDER BY Y.COLNAME)
FROM TABLE_B x,ALL_TAB_COLUMNS y
where x.COLNAME=Y.COLUMN_NAME )
||
' FROM Table_A' script
FROM DUAL;
可以使用ref游标来创建动态列。许多语言和应用程序都支持ref游标,如果你添加一些关于你的系统的细节,有人可能知道如何在你的环境中准确地集成它们。
下面是一个简单的例子,说明如何创建一个返回 ref 游标的函数。如何调用它取决于你的系统。
--drop table a;
--drop table b;
create table a as
select 1 col1, 2 col2, 3 col3, 4 col4, 5 col5, 6 col6, 7 col7, 8 col8, 9 col9, 10 col10
from dual;
create table b as
select 'COL1' column_name from dual union all
select 'COL2' column_name from dual union all
select 'COL3' column_name from dual;
create or replace function get_dynamic_results return sys_refcursor is
v_cursor sys_refcursor;
v_column_list varchar2(4000);
begin
--Split this into multiple SELECTS if you get an error like:
-- ORA-01489: result of string concatenation is too long error
select listagg(column_name, ',') within group (order by column_name) columns
into v_column_list
from b;
open v_cursor for 'select '||v_column_list||' from a';
return v_cursor;
end;
/