【问题标题】:Oracle pl sql dynamic using clauseOracle pl sql 动态使用子句
【发布时间】:2015-04-17 14:50:53
【问题描述】:

我对执行立即语句中的“动态使用子句”有疑问。我还需要动态设置“执行立即语句”和 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"

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

【问题讨论】:

  • function1 的功能如何。我认为您必须使用 DBMS_SQL 已经存在的包,而不是返回一个简单的语句。
  • 您所显示的内容实际上有什么问题 - 您是否得到错误或错误的结果?
  • 你从哪里得到“table_list.rec_id”?它不是你的表结构的一部分

标签: oracle dynamic plsql cursor using


【解决方案1】:

非常感谢您的回复。

问题是我假设我不知道表的结构以及游标 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 和记录。

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

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

【讨论】:

    【解决方案2】:

    尝试将您的执行立即替换为充分使用 dbms_sql。 http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sql.htm#i996891

    这个包中的 bind_array 函数对你有用。

    【讨论】:

      【解决方案3】:

      使用动态 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;
      /
      

      【讨论】:

        【解决方案4】:

        您可以使用DBMS_SQL 包:

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

        或者EXECUTE IMMEDIATE的匿名PL/SQL块,执行动态创建的EXECUTE IMMEDIATE(这种方式不适合返回数据)。请参阅@JonHeller 的回答。

        【讨论】:

          猜你喜欢
          • 2016-07-29
          • 1970-01-01
          • 2016-08-28
          • 1970-01-01
          • 2013-06-14
          • 2012-04-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多