You may use DBMS_SQL
package to parse the statement and get the column names:
declare
cur integer;
cols dbms_sql.desc_tab;
num_cols integer;
begin
cur := dbms_sql.open_cursor();
/*Prase statement*/
dbms_sql.parse(
c => cur,
statement => q'{
select dual.*, 'something' as qwe
from dual
}',
language_flag => dbms_sql.native
);
/*Get cols*/
dbms_sql.describe_columns(
c => cur,
col_cnt => num_cols,
desc_t => cols
);
for i in 1..num_cols loop
dbms_output.put('Col index: ' || i);
dbms_output.put_line(' Col name: ' || cols(i).col_name);
end loop;
dbms_sql.close_cursor(cur);
end;
/
dbms_output:
Col index: 1 Col name: DUMMY
Col index: 2 Col name: QWE
Or with a local function declaration, if you want it to be select
able:
with function get_cols(
p_stmt in clob
) return sys.odcivarchar2list
as
pragma autonomous_transaction;
ret sys.odcivarchar2list := sys.odcivarchar2list();
cur integer;
cols dbms_sql.desc_tab;
num_cols integer;
begin
cur := dbms_sql.open_cursor();
/*Prase statement*/
dbms_sql.parse(
c => cur,
statement => p_stmt,
language_flag => dbms_sql.native
);
/*Get cols*/
dbms_sql.describe_columns(
c => cur,
col_cnt => num_cols,
desc_t => cols
);
for i in 1..num_cols loop
ret.extend();
ret(i) := cols(i).col_name;
end loop;
dbms_sql.close_cursor(cur);
return ret;
end;
select column_value as col_names
from get_cols(p_stmt => q'{select dual.*, 'something' as qwe from dual}')
| COL_NAMES |
| :-------- |
| DUMMY |
| QWE |
db<>fiddle here