Oracle pl sql动态使用子句

时间:2015-04-17 14:50:54

标签: oracle dynamic plsql cursor using

我有一个关于"动态使用条款"的问题在执行立即声明。我需要动态设置"执行立即声明"以及使用条款。我不知道表结构,但我只知道表的名称,我需要对其进行操作更新。

所以我编写了一个函数(通过user_tab_columns和user user_constraints表)来设置一个带有update语句和bind_variable的变量,但是现在我需要使用变量列表设置using子句。

示例:

CREATE TABLE table1
(
  rec1  VARCHAR2(10 BYTE)           NULL,
  rec2       DATE                          NULL,
  rec3 number(9) not null
);

 declare
 TYPE cur_type IS REF CURSOR;
 cur cur_type;
 table_list table1%ROWTYPE;
 sqlstring varchar2(400);

 begin
 OPEN cur FOR sqlstring;
 LOOP
    FETCH cur INTO table_list;
    EXIT WHEN cur%NOTFOUND;
    sqlstring:=function1('table1');
    -- that returns sqlstring:='update table1 set rec1=:1 , rec2=:2 , rec3=:3 where rec_id=:c4';

    execute immediate sqlstring using table_list.rec1, table_list.rec2, table_list.rec3, table_list.rec_id;
END LOOP;
close cur;
end;

我需要动态地实现游标table_list的变量列表。

"使用table_list.rec1,table_list.rec2,table_list.rec3,table_list.rec_id"

立即执行sqlstring

有人知道如何解决这个问题吗?

4 个答案:

答案 0 :(得分:0)

非常感谢您的回复。

问题是我假设我不知道表的结构,因此游标table_list table1%ROWTYPE的变量列表。 所以我不能在using子句中明确表示table_list.rec1,table_list.rec2 ....

如果我只使用table_list作为变量

begin
OPEN cur FOR sqlstring;
LOOP
    FETCH cur INTO table_list;
    EXIT WHEN cur%NOTFOUND;
    sqlstring:=function1('table1');
execute immediate sqlstring using table_list;
END LOOP;
close cur;

我收到错误:“00457表达式必须是SQL类型”

http://psoug.org/oraerror/PLS-00457.htm

错误原因: 错误类型的表达式在USING或动态RETURNING子句中。在USING或动态RETURNING子句中,表达式不能是非SQL类型,例如BOOLEAN,INDEX TABLE和record。

我首先需要一种方法来不仅检索值而且还检查游标table_list的变量列表。 但也许这是不可能的,我必须找到一个解决方法。

如果我发现一些有趣的东西,我会发布。 三江源。

答案 1 :(得分:0)

尝试将execute immediate替换为完全使用dbms_sql。 http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sql.htm#i996891

对你有用的将是来自这个包的bind_array函数。

答案 2 :(得分:0)

使用动态PL / SQL,除非您可以重新考虑原始语句并将值插入其中。

declare
    v_string constant varchar2(32767) := 'update test1 set a = :1, b = :2';
    v_using_string varchar2(32767);
begin
    --Create dynamic using string.
    --For example, let's say you want to pass in the values "1" for each NUMBER column.
    select listagg(1, ',') within group (order by null)
    into v_using_string
    from user_tab_columns
    where table_name = 'TEST1'
        and data_type = 'NUMBER';

    --Execute the original dynamic SQL, adding the USING string.
    execute immediate '
        begin
            execute immediate '''||v_string||''' using '||v_using_string||';
        end;
    ';
end;
/

答案 3 :(得分:0)

您可以使用DBMS_SQL包:

  1. 使用dbms_sql.open_cursor
  2. 打开游标
  3. 使用dbms_sql.parse
  4. 解析语句
  5. 使用dbms_sql.bind_variable
  6. 在循环中绑定变量
  7. 使用dbms_sql.execute
  8. 执行声明
  9. 最后使用dbms_sql.close_cursor
  10. 关闭光标

    EXECUTE IMMEDIATE匿名PL / SQL块,执行动态创建的EXECUTE IMMEDIATE(此方法不适合返回数据)。见@JonHeller的回答。