问题
I am trying to execute a procedure into which i send the table name and 2 column names as parameters:
EXECUTE IMMEDIATE 'select avg(@column1) from @Table1 where REF_D = @column2' into ATTR_AVG;
I have tried using the variables in combiations of '@'
, ':'
, '||'
but nothing seems to work.
Has anyone used table names as a parameter. there are a few solutions here but for SQL Server
回答1:
You can only use bind variables (denoted by colons) for values, not for parts of the structure. You will have to concatenate the table and column names into the query:
EXECUTE IMMEDIATE 'select avg(' || column1 | ') from ' || Table1
|| ' where REF_D = ' || column2 into ATTR_AVG;
Which implies REF_D
is a fixed column name that can appear in any table you'll call this for; in a previous question that seems to be a variable. If it is actually a string variable then you'd need to bind and set that:
EXECUTE IMMEDIATE 'select avg(' || column1 | ') from ' || Table1
|| ' where ' || column2 || ' = :REF_D' into ATTR_AVG using REF_D;
If it's supposed to be a date you should make sure the local variable is the right type, or explicitly convert it.
回答2:
You need to construct the executable statement using ||
(or else define it as one string containing placeholders that you can then manipulate with replace
). Something like:
create or replace procedure demo
( p_table user_tab_columns.table_name%type
, p_column1 user_tab_columns.column_name%type
, p_column2 user_tab_columns.column_name%type )
is
attr_avg number;
begin
execute immediate
'select avg(' || p_column1 || ') from ' || p_table ||
' where ref_d = ' || p_column2
into attr_avg;
dbms_output.put_line('Result: ' || attr_avg);
end demo;
It's generally a good idea to build the string in a debugger-friendly variable first, i.e. something like:
create or replace procedure demo
( p_table user_tab_columns.table_name%type
, p_column1 user_tab_columns.column_name%type
, p_column2 user_tab_columns.column_name%type )
is
attr_avg number;
sql_statement varchar2(100);
begin
sql_statement :=
'select avg(' || p_column1 || ') from ' || p_table ||
' where ref_d = ' || p_column2;
execute immediate sql_statement into attr_avg;
dbms_output.put_line('Result: ' || attr_avg);
end demo;
Depending on what ref_d
is, you may have to be careful with what you compare it to, so the above could require some more work, but hopefully it gives you the idea.
Edit: however see Alex Poole's answer for a note about the use of bind variables. If ref_d
is a variable that may need to become:
sql_statement :=
'select avg(' || p_column1 || ') from ' || p_table ||
' where ' || p_column2 || ' = :b1';
execute immediate sql_statement into attr_avg using ref_d;
(The convention is to put the search expression on the right e.g. where name = 'SMITH'
rather than where 'SMITH' = name
, though they are the same thing to SQL.)
来源:https://stackoverflow.com/questions/43211749/dynamic-sql-with-table-name-as-a-parameter