【问题标题】:Oracle - How to add a Record to a Collection of the same Type (Multiset Union)Oracle - 如何将记录添加到相同类型的集合中(多集联合)
【发布时间】:2019-09-15 06:34:39
【问题描述】:

我使用MULTISET UNION 将一个集合加载到另一个相同类型的集合中,但是我现在正在使用 Records 并希望将 Record 添加到同一类型的集合。无论出于何种原因,我都无法找出适当的语法或只是正确的方法来执行此操作,因为 MULTISET UNION 似乎无法像我习惯使用 Collections 那样与 Records 配合使用。

我在最后添加了这段代码如何工作的摘要(无论如何都应该工作)。

截图和代码如下

LINE 44: c_los_ms_tbl_ret := c_los_ms_tbl_ret MULTISET UNION los_ms_row;

DECLARE  

  TYPE t_los_ms_rec IS RECORD(
      appt_id NUMBER DEFAULT NULL,
      appt_name VARCHAR(300) DEFAULT NULL,
      tot_units NUMBER DEFAULT 0,
      new_rentals NUMBER DEFAULT 0,
      term_rentals NUMBER DEFAULT 0,
      avg_los_all NUMBER DEFAULT 0
  );

  TYPE t_los_ms_tbl IS TABLE OF t_los_ms_rec;

  /* Two collections based on Table Type of Record t_los_ms_rec */
  c_los_ms_tbl_ret  t_los_ms_tbl  :=  t_los_ms_tbl();  
  c_los_ms_tbl      t_los_ms_tbl  :=  t_los_ms_tbl();  

  FUNCTION los_func(p_appt_ids IN VARCHAR) RETURN t_los_ms_tbl
  IS
        los_ms_row  t_los_ms_rec; /* Declare Row based on Record Type */

  BEGIN
    /* Outer loop: iterate through all user selected appartments. */
    FOR los IN 
    (
      SELECT 1001 AS appt_id, 45 AS tot_units, 10 AS new_rentals, 3 AS term_rentals, 'Building1' AS appt_name
        FROM dual UNION ALL
      SELECT 1002 AS appt_id, 37 AS tot_units, 6  AS new_rentals, 4 AS term_rentals, 'Building2' AS appt_name
        FROM duaL
    )
    LOOP      
      /* Set Row Fields to the Data being returned by Outer Loop.  Fake Table data from dual. */
      los_ms_row.appt_name    := los.appt_name;      
      los_ms_row.appt_id      := los.appt_id;
      los_ms_row.new_rentals  := los.new_rentals;
      los_ms_row.term_rentals := los.term_rentals;
      los_ms_row.tot_units    := los.tot_units;
      los_ms_row.avg_los_all  := 45; /* Made up Number */

      /* Output Apartment Name for testing */
      dbms_output.put_line('Apartment Name' || los_ms_row.appt_name);

      /* Save Row Data into Collection */ /* HOW DO I POPULATE COLLECTION WITH A RECORD */
      c_los_ms_tbl_ret  := c_los_ms_tbl_ret MULTISET UNION los_ms_row;

    END LOOP;

    RETURN c_los_ms_tbl_ret; /* Return Populated Collection */

  END los_func;  

BEGIN  
  /* Call Function and Store Returned Collection into a collection of same type */
  c_los_ms_tbl  :=  los_func(p_appt_ids => '1001,1002');

  FOR r IN c_los_ms_tbl.FIRST .. c_los_ms_tbl.LAST
  LOOP
    dbms_output.put_line(c_los_ms_tbl(r).avg_los_all);
  END LOOP;

END;

总结

  • 已声明记录类型。 t_los_ms_rec
  • 根据记录 t_los_ms_tbl 声明的表类型
  • 基于表类型c_los_ms_tbl_retc_los_ms_tbl 声明的两个集合

  • 在主脚本的 BEGIN 块中,函数 los_func() 返回一个类型为 t_los_ms_tbl 的集合,它使用公寓 ID 作为其参数来调用。

  • LINE 20:los_func() 内,一个Row 被声明为los_ms_row,属于同一类型t_los_ms_rec。此行的字段是使用虚假数据填充的。
  • 接下来是一次填充一个的集合。 想不通
  • 此时,当注释掉 LINE 44 时,我尝试填充集合,公寓名称已成功发送到 dbms_output。这是由于我不知道如何将已成功填充数据的记录获取到集合c_los_ms_tbl_ret 中而中断的地方。

错误报告-

ORA-06550:第 44 行,第 32 列: PLS-00306:调用“MULTISET_UNION_ALL”时参数的数量或类型错误

【问题讨论】:

    标签: plsql oracle11g multiset


    【解决方案1】:

    MULTISET UNION 用于从两个嵌套表创建一个嵌套表。您正在尝试使用 MULTISET UNION 将嵌套表和单个记录连接在一起。

    有两种方法可以解决此问题:

    1. 从单个记录中创建一个元素表:

          c_los_ms_tbl_ret  := c_los_ms_tbl_ret MULTISET UNION t_los_ms_tbl(los_ms_row);
      
    2. 放弃使用MULTISET UNION,只需将新记录附加到表中:

          c_los_ms_tbl_ret.EXTEND(1);
          c_los_ms_tbl_ret(c_los_ms_tbl_ret.COUNT) := los_ms_row;
      

    【讨论】:

    • @LuckWoodward 非常好。两者都有效。好奇你是否对性能有任何了解。我的假设是 MULTISET UNION 的负载会更重,但我不相信我在这里有足够的经验可以肯定地说出一种或另一种方式。想法?
    • 我的直觉说第二个会更快,但我不确定两者之间是否存在巨大的性能差异。如果您确实关心性能问题,请尝试两种选择,看看哪一种效果更快。
    猜你喜欢
    • 1970-01-01
    • 2011-03-03
    • 2015-10-24
    • 1970-01-01
    • 2016-05-17
    • 2019-02-08
    • 2011-08-31
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多