如何通过使用代码更改变量名称来动态使用变量

Posted

技术标签:

【中文标题】如何通过使用代码更改变量名称来动态使用变量【英文标题】:How can i use variables dynamically by changing their names using code 【发布时间】:2019-11-05 08:48:01 【问题描述】:

想要一种通过在 plsql 块中动态更改名称来引用不同变量的方法。

尝试使用简单的循环来更改变量的有效名称。 使用语句编写级联 plsql 块,但由于现有代码的大小,它没有用。

set serveroutput on;
declare
foo1 number:=111;
foo2 number:=222;
begin
execute immediate 'dbms_output.put_line(foo'||'1)';
for i in 0..2
loop
dbms_output.put_line(foo||i);
end loop;
end;
/

预期输出为 111 输出错误如下 错误报告 - ORA-00900: 无效的 SQL 语句 ORA-06512: 在第 5 行 00900. 00000 - “无效的 SQL 语句”

【问题讨论】:

“想要一种通过在 plsql 块中动态更改名称来引用不同变量的方法” 这不是 PL/SQL 的工作方式。因此,请说明您要解决的业务问题,我们可以提供适当的解决方案。 【参考方案1】:

您的变量是本地的。 DBMS_OUTPUT 包不知道它们。所以生成的字符串dbms_output.put_line(foo1)不能用execute immediate执行。

解决这个问题的典型方法是使用值数组而不是单独的变量:

declare
  type t_array is varray(2) of integer;
  v_array t_array := t_array(111, 222);
begin
  for i in 1..2 loop
    dbms_output.put_line(v_array(i));
  end loop;
end;

动态数组也一样:

declare
  type t_array is table of integer;
  v_array t_array := t_array();
begin
  v_array.extend(1);
  v_array(1) := 111;
  v_array.extend(1);
  v_array(2) := 222;
  for i in 1 .. v_array.count loop
    dbms_output.put_line(v_array(i));
  end loop;
end;

【讨论】:

感谢 Thorsten 的解决方案,但我们可以使用动态数组而不是静态 varray(2) 吗? 是的,当然。我已经相应地更新了我的答案。【参考方案2】:

让我们一步一步来。首先,有效的静态代码:

SQL> declare
  2  foo1 number:=111;
  3  foo2 number:=222;
  4  begin
  5  dbms_output.put_line(foo1);
  6  end;
  7  /

111

现在,如果你想立即执行一些文本,你必须把所有代码放在文本中:

SQL> declare
  2    l_code_block varchar2(4000) := '
  3  declare
  4  foo1 number:=111;
  5  foo2 number:=222;
  6  begin
  7  dbms_output.put_line(foo2);
  8  end;
  9  ';
 10  begin
 11  execute immediate l_code_block;
 12  end;
 13  /

222

下一步:如果我们想动态改变一个,我们可以而且应该使用“绑定变量”。

SQL> declare
  2    l_code_block varchar2(4000) := '
  3  declare
  4  foo1 number:=111;
  5  foo2 number:=222;
  6  begin
  7  dbms_output.put_line(:n);
  8  end;
  9  ';
 10  begin
 11  execute immediate l_code_block using 1;
 12  end;
 13  /

1

但是如果我们尝试使用绑定变量来更改代码,它就不起作用了。

SQL> declare
  2    l_code_block varchar2(4000) := '
  3  declare
  4  foo1 number:=111;
  5  foo2 number:=222;
  6  begin
  7  dbms_output.put_line(foo:n);
  8  end;
  9  ';
 10  begin
 11  execute immediate l_code_block using 1;
 12  end;
 13  /

...
Error report -
ORA-06550: line 6, column 25:
PLS-00103: Encountered the symbol "" when expecting one of the following
...

所以如果我们想动态改变代码,我们必须对文本做一个REPLACE。

SQL> declare
  2    l_code_block varchar2(4000) := '
  3  declare
  4  foo1 number:=111;
  5  foo2 number:=222;
  6  begin
  7  dbms_output.put_line(foo#N#);
  8  end;
  9  ';
 10  begin
 11  execute immediate replace(l_code_block,'#N#',1);
 12  end;
 13  /

111

最后,这是你的循环:

SQL> declare
  2    l_code_block varchar2(4000) := '
  3  declare
  4  foo1 number:=111;
  5  foo2 number:=222;
  6  begin
  7  dbms_output.put_line(foo#N#);
  8  end;
  9  ';
 10  begin
 11    for i in 1..2 loop
 12      execute immediate replace(l_code_block,'#N#',i);
 13    end loop;
 14  end;
 15  /

111
222

请理解,我正在尝试按要求回答您的问题。应尽可能避免这种“动态”方法,而且几乎总是可行的。我们必须支持业务需求才能推荐最合适的技术。

最好的问候, 炖阿什顿

【讨论】:

很好地描述了如何使用动态 pl/sql 将一个简单的 6 行代码块变成两倍多的噩梦。 谢谢你炖,我试过这个,但我的 plsql 块非常大。有什么办法不必将查询存储在变量中? 我以为我已经回答了这个问题。答案是不。有什么方法可以说服你放弃并尝试另一种方法?

以上是关于如何通过使用代码更改变量名称来动态使用变量的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中使用动态名称分配变量

在 Java 中使用动态名称分配变量

php中的动态函数名

如何在 React 中创建动态变量名?

如何通过 PL/SQL 过程和表名作为变量打印动态 SQL 中的所有表行?

动态变量名称以在 for 循环中改变变量