在 PL/SQL 中创建动态对象

Create Dynamic Objects in PL/SQL

我是 PL/SQL 的新手,目前我需要一个特定的功能,我怀疑 PL/SQL 无法实现。我注定要使用 PL/SQL,因此不幸的是,关于其他编程 ('query') 语言的提示对我来说毫无用处。 因此,我想问一下,是否可以在程序流程期间而不是仅在 DECLARE 块内在 PL/SQL 中创建用户定义类型的实例,如果可能的话,我想知道怎么做。

场景:

我想创建一个列表列表,例如...

TYPE SIMPLE_LIST IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR(30);
TYPE LIST_OF_LISTS IS TABLE OF SIMPLE_LIST INDEX BY VARCHAR2(30);

类型的创建没有任何问题。

在我的程序中,有一个函数,需要声明这样一个LIST_OF_LISTS并动态填充

因此简化的代码示例应如下所示...

FUNCTION foo(...) RETURN ...
AS
  ll LIST_OF_LISTS;
  sl SIMPLE_LIST;
  ...
BEGIN
  LOOP  -- iterate over something
  ...
  sl := new SIMPLE_LIST; -- this surely doesn't work
  sl('key1') := ...;
  sl('key2') := ...;
  sl('key3') := ...;
  ...
  ll('iter_key') := sl;
  END LOOP;
  RETURN ll;
END foo;

我want/need使用这样的列表列表,因为我无法在运行前确定每个列表(也不是列表列表)的长度。

正如人们已经知道的那样,我正在寻找一种类似 OO 的功能来创建一个类型的实例,其中包含类似 'new' 运算符的东西,就在程序流的中间,以动态填充列表列表。带有 'new'-operator 的那一行只是我想要完成的事情的提示,因为我知道这不是包含所描述任务的方法。

任何人都可以提示我如何使用 PL/SQL 来实现所描述的场景吗?

编辑

由于可能有人感兴趣,这里有一些关于我试图完成的实际任务的更多背景信息。简而言之,函数 'foo' 应从 xml 文档中提取一些项目,并将结果 return 打包在数据结构中供以后处理,这就是我最终采用该方法的原因使用这样的列表列表。 函数 foo 接收一个 xml 文档 (XMLTYPE),以及在文档解析期间要搜索的项目列表。在解析文档时,使用 DBMS_XMLDOM-package,列表中填充了每个 XML 标记的键和值,这些标记与要搜索的元素之一相匹配。由于 XML 标签在整个文档中可能不是唯一的,而是多次出现,我想出了使用定义的 SIMPLE_LIST 来存储每次出现的值的想法XML tags/elements 要搜索的(键)。因此 LIST_OF_LISTS 的 'key'/'index' 最终应包含 XML tag/element 的名称,而 SIMPLE_LIST 应包含任何的所有值出现相应的 XML tag/element,打包在一个列表中。 列表中要 returned 的条目数量将相当小(绝对不超过 100 个条目),因此我认为在这种情况下使用实际表或嵌套表可能有点矫枉过正。

提前致谢。

克里斯

编辑²

我测试了 Boneist 和 Łukasiewicz 先生的答案,我可以确认它们在应用于我的场景时都有效。我接受了后者,因为它是最紧凑的答案。

再次感谢您解决我的问题。

干杯, 克里斯

也许这有帮助。

    declare 
      TYPE SIMPLE_LIST IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR(30);
      TYPE LIST_OF_LISTS IS TABLE OF SIMPLE_LIST INDEX BY VARCHAR2(30);
        ll LIST_OF_LISTS;
        key_ll VARCHAR2(30);
        key_sl  VARCHAR2(30); 
    BEGIN
    --dynamic 
     for i in 1 .. 10 loop
        for j in 1..10 loop
          ll('i='||i)('j='||j) := 'value='||j;
        end loop;
     end loop;
-- static
     ll('A')('1'):='A1';
     ll('A')('2'):='A2';
     ll('A')('3'):='A3';
     ll('A')('4'):='A4';
     ll('A')('5'):='A5';    
     ll('B')('1'):='B1';
     ll('B')('2'):='B2';
     ll('B')('3'):='B3';
     ll('B')('4'):='B4';
     ll('B')('5'):='B5'; 



    -- and how to iterate it.
      key_ll := ll.first;
      while (key_ll is not null)
         loop
              key_sl := ll(key_ll).first;
              dbms_output.put_line(key_ll);
              while (key_sl is not null)
                 loop
                    dbms_output.put_line('   key sl: '||key_sl||' value sl: '||ll(key_ll)(key_sl));
                     key_sl :=  ll(key_ll).next(key_sl);
              end loop;

             key_ll := ll.next(key_ll);
      end loop;
    END foo;

我正在努力想出一个合理的理由来说明为什么您可能想要做嵌套关联数组这样的事情,但是在不知道您要解决什么问题的情况下,很难提出更好的建议做事的方式(尽管很可能存在!)。

话虽这么说,我认为您正在努力解决的是一种将嵌套关联数组(即您示例中的 simple_list 数组)重置为空的方法,对于 list_of_lists 外部数组。有两种方法 - 一种是在处理 sl 数组的内容后使用 sl.delete(),另一种是在处理中添加一个匿名 PL/SQL 块。

这是后者的一个例子:

declare
  type simple_list is table of varchar2(30) index by varchar(30);
  type list_of_lists is table of simple_list index by varchar2(30);

  ll_main list_of_lists;
  sub_sl_main simple_list;

  ll_idx varchar2(30);
  sl_idx varchar2(30);

  function foo
  return list_of_lists
  is
    ll list_of_lists;
  begin
    for j in 1..5
    loop

      declare
        sl simple_list;
      begin
        for i in 1..10
        loop
          if mod(i, j) = 0 then
            sl('key'||i) := 'value '||j||'_'||i;
          end if;
        end loop;

        ll('iter_key'||j) := sl;
      end;


    end loop;

    return ll;
  end;
begin
  ll_main := foo;

  ll_idx := ll_main.first;

  while (ll_idx is not null)
  loop    
    sub_sl_main := ll_main(ll_idx);

    sl_idx := sub_sl_main.first;

    while (sl_idx is not null)
    loop
      dbms_output.put_line('ll_idx = '||ll_idx||' and sl_idx = '||sl_idx||' and sub-list value = '||sub_sl_main(sl_idx));
      sl_idx := sub_sl_main.next(sl_idx);
    end loop;

    ll_idx := ll_main.next(ll_idx);
  end loop;
end;
/

ll_idx = iter_key1 and sl_idx = key1 and sub-list value = value 1_1
ll_idx = iter_key1 and sl_idx = key10 and sub-list value = value 1_10
ll_idx = iter_key1 and sl_idx = key2 and sub-list value = value 1_2
ll_idx = iter_key1 and sl_idx = key3 and sub-list value = value 1_3
ll_idx = iter_key1 and sl_idx = key4 and sub-list value = value 1_4
ll_idx = iter_key1 and sl_idx = key5 and sub-list value = value 1_5
ll_idx = iter_key1 and sl_idx = key6 and sub-list value = value 1_6
ll_idx = iter_key1 and sl_idx = key7 and sub-list value = value 1_7
ll_idx = iter_key1 and sl_idx = key8 and sub-list value = value 1_8
ll_idx = iter_key1 and sl_idx = key9 and sub-list value = value 1_9
ll_idx = iter_key2 and sl_idx = key10 and sub-list value = value 2_10
ll_idx = iter_key2 and sl_idx = key2 and sub-list value = value 2_2
ll_idx = iter_key2 and sl_idx = key4 and sub-list value = value 2_4
ll_idx = iter_key2 and sl_idx = key6 and sub-list value = value 2_6
ll_idx = iter_key2 and sl_idx = key8 and sub-list value = value 2_8
ll_idx = iter_key3 and sl_idx = key3 and sub-list value = value 3_3
ll_idx = iter_key3 and sl_idx = key6 and sub-list value = value 3_6
ll_idx = iter_key3 and sl_idx = key9 and sub-list value = value 3_9
ll_idx = iter_key4 and sl_idx = key4 and sub-list value = value 4_4
ll_idx = iter_key4 and sl_idx = key8 and sub-list value = value 4_8
ll_idx = iter_key5 and sl_idx = key10 and sub-list value = value 5_10
ll_idx = iter_key5 and sl_idx = key5 and sub-list value = value 5_5

不过,我几乎可以肯定有更好的方法来完成您想要的事情!