Although you can construct dynamic queries by concatenating values, it's generally better to use bind variables where possible, for example:
execute immediate
'select column_name from user_tab_columns where table_name = :b1'
bulk collect into input_cols
using p_table;
I recommend getting into the habit of anchoring types in your code to the corresponding database object, when there is one. For example, this:
mapping_table dba_tab_columns.table_name%type
instructs the compiler to look up the type of dba_tab_columns.table_name
and use that. However, I would generally avoid the dba_
views in procedures like this and stick to user_
views, e.g. user_tab_columns
, to limit them to objects you own. If you must use dba_
views, you should also include the table owner, as there may be more than one table with the same name.
I also prefer to name my parameters in a way that separates them from column names etc. There are various conventions (camelCase, prefixing with i_
for in
or p_
for parameter, prefixing with the procedure name e.g. map_values.mapping_table
), so pick one you like.
Putting that together, you get something like this:
create or replace procedure map_values
( p_table user_tab_columns.table_name%type )
as
type col_names is table of user_tab_columns.column_name%type;
input_cols col_names;
begin
execute immediate
'select column_name from user_tab_columns where table_name = :b1 order by column_id'
bulk collect into input_cols
using p_table;
for i in 1..input_cols.count loop
dbms_output.put_line(input_cols(i));
end loop;
end map_values;
Or, if you don't specifically need a collection and just want to loop through a result set:
create or replace procedure map_values
( p_table user_tab_columns.column_name%type )
as
columns_cur sys_refcursor;
colname user_tab_columns.column_name%type;
begin
open columns_cur for
'select column_name from user_tab_columns where table_name = :b1 order by column_id'
using p_table;
loop
fetch columns_cur into colname;
exit when columns_cur%notfound;
dbms_output.put_line(colname);
end loop;
close columns_cur;
end;
As Koen pointed out in the comments, though, there is no need for dynamic SQL in this example, so a much simpler version could be just:
create or replace procedure map_values
( p_table user_tab_columns.column_name%type )
as
begin
for r in (
select column_name from user_tab_columns
where table_name = p_table
order by column_id
)
loop
dbms_output.put_line(r.column_name);
end loop;
end map_values;