在PL / SQL中创建动态对象

时间:2015-10-15 10:41:28

标签: sql oracle dynamic

我是PL / SQL的新手,目前我需要一个特定的功能,我怀疑它不适用于PL / SQL。我一定会使用PL / SQL,所以很遗憾对其他编程('查询')语言的提示对我没用。 因此,我想问一下,是否有可能在程序流程中在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);

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

在我的程序中,我有一个函数,需要声明这样的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;

我想/需要使用这样的列表列表,因为在运行之前我无法确定每个列表的长度(也不能确定列表列表的长度)。

正如人们已经知道的那样,我正在寻找类似于OO的功能来创建一个类型的实例,类似于'new'运算符,就在程序流程的中间,填写列表动态列出。带有“new”运算符的行只是对我想要完成的事情的暗示,因为我知道这不是包含所描述任务的方式。

任何人都可以给我一个提示,告诉我如何使用PL / SQL实现所描述的场景吗?

修改

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

提前致谢。

克里斯

EDIT²

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

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

干杯, 克里斯

2 个答案:

答案 0 :(得分:1)

也许这有帮助。

    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;

答案 1 :(得分:0)

我很难想到一个有效的理由,为什么你可能想要做一个嵌套的关联数组这样的事情,但不知道你想要解决什么问题,这很难建议一个更好的做法(虽然它很可能存在!)。 话虽这么说,我认为你正在努力解决的问题是通过list_of_lists外部数组的每次迭代,将嵌套的关联数组(在你的例子中为simple_list)重置为空。有两种方法 - 一种是在使用sl数组的内容后使用sl.delete(),另一种是在处理中添加匿名PL / SQL块。 这是后者的一个例子: 宣布   type simple_list是varchar(30)的varchar2(30)索引表;   type list_of_lists是varchar2(30)的simple_list索引表;   ll_main list_of_lists;   sub_sl_main simple_list;   ll_idx varchar2(30);   sl_idx varchar2(30);   功能foo   return list_of_lists   是     ll list_of_lists;   开始     对于j在1..5     环       宣布         sl simple_list;       开始         我在1..10         环           如果mod(i,j)= 0那么             sl(' key' || i):=' value' || j ||' _' || i;           万一;         结束循环;         ll(' iter_key' || j):= sl;       结束;     结束循环;     返回ll;   结束; 开始   ll_main:= foo;   ll_idx:= ll_main.first;   while(ll_idx不为null)   环     sub_sl_main:= ll_main(ll_idx);     sl_idx:= sub_sl_main.first;     while(sl_idx不为null)     环       dbms_output.put_line(' ll_idx =' || ll_idx ||'和sl_idx =' || sl_idx ||'和子列表值=' | | sub_sl_main(sl_idx));       sl_idx:= sub_sl_main.next(sl_idx);     结束循环;     ll_idx:= ll_main.next(ll_idx);   结束循环; 结束; / ll_idx = iter_key1和sl_idx = key1和子列表值=值1_1 ll_idx = iter_key1和sl_idx = key10,子列表值=值1_10 ll_idx = iter_key1和sl_idx = key2和子列表值=值1_2 ll_idx = iter_key1和sl_idx = key3和子列表值=值1_3 ll_idx = iter_key1和sl_idx = key4,子列表值=值1_4 ll_idx = iter_key1和sl_idx = key5和子列表值=值1_5 ll_idx = iter_key1和sl_idx = key6和子列表值=值1_6 ll_idx = iter_key1和sl_idx = key7和子列表值=值1_7 ll_idx = iter_key1和sl_idx = key8,子列表值=值1_8 ll_idx = iter_key1和sl_idx = key9,子列表值=值1_9 ll_idx = iter_key2和sl_idx = key10和子列表值=值2_10 ll_idx = iter_key2和sl_idx = key2和子列表值=值2_2 ll_idx = iter_key2和sl_idx = key4,子列表值=值2_4 ll_idx = iter_key2和sl_idx = key6,子列表值=值2_6 ll_idx = iter_key2和sl_idx = key8,子列表值=值2_8 ll_idx = iter_key3和sl_idx = key3和子列表值=值3_3 ll_idx = iter_key3和sl_idx = key6和子列表值=值3_6 ll_idx = iter_key3和sl_idx = key9和子列表值=值3_9 ll_idx = iter_key4和sl_idx = key4和子列表值=值4_4 ll_idx = iter_key4和sl_idx = key8,子列表值=值4_8 ll_idx = iter_key5和sl_idx = key10和子列表值=值5_10 ll_idx = iter_key5和sl_idx = key5和子列表值=值5_5 不过,我几乎可以肯定,有更好的方法可以做你以后的事情!