虽然您可以通过连接值来构造动态查询,但通常最好尽可能使用绑定变量,例如:
execute immediate
'select column_name from user_tab_columns where table_name = :b1'
bulk collect into input_cols
using p_table;
我建议养成将代码中的类型锚定到相应数据库对象(如果有的话)的习惯。例如,这个:
mapping_table dba_tab_columns.table_name%type
指示编译器查找dba_tab_columns.table_name 的类型并使用它。但是,我通常会避免在这样的过程中使用dba_ 视图并坚持使用user_ 视图,例如user_tab_columns,将它们限制为您拥有的对象。如果必须使用dba_ 视图,还应包括表所有者,因为可能有多个同名表。
我也更喜欢以将参数与列名等分开的方式命名参数。有各种约定(camelCase,前缀为i_ 用于in 或p_ 用于参数,前缀为过程名称,例如map_values.mapping_table),所以选择一个你喜欢的。
把它们放在一起,你会得到这样的东西:
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;
或者,如果您并不特别需要一个集合,而只是想遍历一个结果集:
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;
正如 Koen 在 cmets 中指出的那样,在此示例中不需要动态 SQL,因此更简单的版本可能只是:
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;