以 table 名称作为参数的动态 SQL

Dynamic SQL with table name as a parameter

我正在尝试执行一个过程,我将 table 名称和 2 个列名称作为参数发送到其中:

EXECUTE IMMEDIATE 'select avg(@column1) from @Table1 where REF_D = @column2' into ATTR_AVG;

我试过在 '@'':''||' 的组合中使用变量,但似乎没有任何效果。

有没有人用过table名字作为参数。这里有一些解决方案,但 SQL 服务器

您只能将绑定变量(用冒号表示)用于值,而不能用于结构的一部分。您必须将 table 和列名连接到查询中:

EXECUTE IMMEDIATE 'select avg(' || column1 | ') from ' || Table1 
  || ' where REF_D = ' || column2 into ATTR_AVG;

这意味着 REF_D 是一个固定的列名称,可以出现在任何 table 中,您将为此调用它;在上一个问题中,这似乎是一个变量。如果它实际上是一个字符串变量,那么您需要绑定并设置它:

EXECUTE IMMEDIATE 'select avg(' || column1 | ') from ' || Table1 
  || ' where ' || column2 || ' = :REF_D' into ATTR_AVG using REF_D;

如果它应该是一个日期,你应该确保局部变量是正确的类型,或者明确地转换它。

您需要使用 || 构造可执行语句(或者将其定义为一个包含占位符的字符串,然后您可以使用 replace 对其进行操作)。类似于:

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;

通常最好先在调试器友好的变量中构建字符串,例如:

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;

根据 ref_d 是什么,您可能需要小心比较它,因此以上内容可能需要更多工作,但希望它能给您一些想法。

编辑:但是请参阅 Alex Poole 的回答以获取有关使用绑定变量的注释。如果 ref_d 是一个变量,可能需要变成:

    sql_statement :=
        'select avg(' || p_column1 || ') from ' || p_table ||
        ' where ' || p_column2 || ' = :b1';

    execute immediate sql_statement into attr_avg using ref_d;

(惯例是将搜索表达式放在右边,例如 where name = 'SMITH' 而不是 where 'SMITH' = name,尽管它们与 SQL 是一样的。)