简体   繁体   English

在PL / SQL中创建动态对象

[英]Create Dynamic Objects in PL/SQL

I'm pretty new to PL/SQL and currently I have the need for a specific functionality, which I suspect to not being doable with PL/SQL. 我是PL / SQL的新手,目前我需要特定的功能,我怀疑它不能与PL / SQL一起使用。 I am bound to using PL/SQL, so hints on other programming ('query') languages will unfortunately be of no use to me. 我必须使用PL / SQL,因此不幸的是,其他编程语言(“查询”)的提示对我毫无用处。 Therefore I'd like to ask, whether it is possible to create instances of user-defined types in PL/SQL during program flow and not only within the DECLARE block, and in case it is possible, I'd like to know how to do it. 因此,我想问一下,是否有可能在程序流程期间以及不仅在DECLARE块内在PL / SQL中创建用户定义类型的实例,并且在可能的情况下,我想知道如何做吧。

Scenario: 场景:

I want to create a list of lists like... 我想创建一个列表列表,例如...

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);

The creation of the type works without any problems. 类型的创建没有任何问题。

In my program, I have a function, which has the need to declare such a LIST_OF_LISTS and fill it dynamically. 在我的程序中,我有一个函数,需要声明一个这样的LIST_OF_LISTS并动态填充它。

Therefore the simplified code sample shall look like... 因此,简化的代码示例应类似于...

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;

I want/need to use such a list of lists, because I cannot determine the length of each list (and also not of the list of lists) before runtime. 我想要/需要使用这样的列表列表,因为在运行时之前我无法确定每个列表的长度(也不能确定列表的列表长度)。

As one can already tell, I'm looking for an OO-like functionality to create an instance of a type with something like a 'new'-operator, right in the middle of the program flow, to fill the list of lists dynamically. 就像已经知道的那样,我正在寻找一种类似于OO的功能,以在程序流程的中间创建一个带有“ new”运算符之类的类型的实例,以动态填充列表列表。 The line with the 'new'-operator is just a hint on what I want to accomplish, as I am aware that this is not the way to encompass the described task. “ new”运算符只是我要完成的任务的提示,因为我知道这不是包含所描述任务的方式。

Can anyone give me a hint on how I might be able to implement the described scenario using PL/SQL? 谁能给我提示我如何使用PL / SQL来实现所描述的方案?

EDIT 编辑

As it might be of interest, here's a little more background information on the actual task I am trying to achieve. 您可能会感兴趣,这里有一些有关我要完成的实际任务的背景信息。 In a nutshell, the function 'foo' shall extract a few items from an xml document and return the result packed in a data structure for later processing, which is why I ended up with the approach of using such a list of lists. 简而言之,函数'foo'将从xml文档中提取一些项目并返回打包在数据结构中的结果以供以后处理,这就是为什么我最终使用了这样的列表列表的原因。 The function foo receives an xml document (XMLTYPE), as well as a list of items to be searched for during the parsing of the document. 函数foo接收一个xml文档(XMLTYPE),以及在文档解析期间要搜索的项目列表。 While the document is being parsed, using the DBMS_XMLDOM-package, the list is filled with key and value of each XML tag that matches one of the elements to be searched for. 在使用DBMS_XMLDOM-package解析文档时,列表中会填充与要搜索的元素之一匹配的每个XML标签的键和值。 Due to the fact, that the XML tags may not be unique across the whole document but occur multiple times, I came up with the idea to use the defined SIMPLE_LIST to store the values of every single occurrence of XML tags/elements (keys) to be searched for. 由于事实,XML标记在整个文档中可能不是唯一的,而是会多次出现,因此我想到了使用定义的SIMPLE_LIST将XML标记/元素(键)每次出现的值存储到的想法。被搜索。 So the 'key'/'index' of LIST_OF_LISTS shall eventually contain the name of the XML tag/element, while the SIMPLE_LIST shall contain all values of any occurrence of the corresponding XML tag/element, packed together in one list. 因此,LIST_OF_LISTS的“键” /“索引”应最终包含XML标签/元素的名称,而SIMPLE_LIST应包含任何出现的相应XML标签/元素的所有值,并打包在一个列表中。 The amount of entries within the list to be returned will be rather small (definitely not more than 100 entries), therefore I assume that the use of actual tables or nested tables might be overkill in this case. 列表中要返回的条目数量将非常小(绝对不超过100个条目),因此,我认为在这种情况下使用实际表或嵌套表可能会过大。

Thanks in advance. 提前致谢。

Chris 克里斯

EDIT² EDIT²

I tested the answers of both Boneist and Mr. Łukasiewicz, and I can confirm that they both worked when applied to my scenario. 我测试了Boneist和Łukasiewicz先生的答案,并且可以确定它们应用于我的场景时都可以使用。 I accepted the latter, due to the fact that it is the most compact answer. 由于这是最紧凑的答案,因此我接受了后者。

Thanks again for solving my problem. 再次感谢您解决我的问题。

Cheers, Chris 克里斯,干杯

Maybe this helps. 也许这会有所帮助。

    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;

I'm struggling to think of a valid reason as to why you might want to do such a thing as a nested associative array, but without knowing what problem you're trying to solve, it's difficult to suggest a better way of doing (although it's highly likely that one exists!). 我正在努力思考为什么可能要执行嵌套嵌套关联数组之类的正当理由,但是在不知道您要解决的问题的情况下,很难提出一种更好的方法(尽管极有可能存在!)。

That being said, what I think you're struggling with is a way to reset the nested associative array (that's the simple_list one in your example) to be empty, for each iteration through the list_of_lists outer array. 话虽如此,我认为您正在苦苦挣扎的是一种通过list_of_lists外层数组的每次迭代将嵌套的关联数组(在您的示例中为simple_list)重置为空的方法。 There are two ways - one is to use sl.delete() once you're doing with the contents of the sl array, and the other is to add an anonymous PL/SQL block into the processing. 有两种方法-一种是在处理sl数组的内容后使用sl.delete(),另一种是在处理中添加一个匿名PL / SQL块。

Here's an example of the latter: 这是后者的一个示例:

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

I'm almost certain there's a better way of doing what you're after, though! 不过,我几乎可以肯定,有一种更好的方法来做您想要做的事情!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM