【问题标题】:oracle add select statement in oracle bulk forall collect looporacle 在 oracle 批量 forall 收集循环中添加选择语句
【发布时间】:2015-11-28 22:24:40
【问题描述】:

我有以下plsql语句:

DECLARE
VPERIODID          VARCHAR2 (10);
vPROCSESSID        NUMBER;
VAUDITORID         NUMBER;

CURSOR c
IS
     SELECT *
      FROM view_cost_noabc
     WHERE OAUDITORID = 477 AND FL <> 'Ο' AND yearid < 2015
  ORDER BY ID;

TYPE nt_type IS TABLE OF c%ROWTYPE;

l_arr              nt_type;   
TYPE vPREVPERIODVALUE IS TABLE OF NUMBER;

vprev              vPREVPERIODVALUE;

dml_errors         EXCEPTION;

BEGIN
  SELECT fn_periodcurrent INTO vPERIODID FROM DUAL;
  SELECT fn_processcurrent INTO vPROCSESSID FROM DUAL;

OPEN c;

LOOP
   FETCH c
   BULK COLLECT INTO l_arr
   LIMIT 500;

   EXIT WHEN l_arr.COUNT = 0;

   BEGIN
      FOR r IN 1 .. l_arr.COUNT
      LOOP
        vprev (r).vPREVPERIODVALUE :=
           'SELECT NVL (SUM (CURRPERIODVALUE), 0)
              FROM LIQUIDATIONSDETAILS
             WHERE     APPOINTOFCAID = l_arr (r).ID
                   AND PROCESSID < vPROCSESSID
                   AND SUBSTR (PROCESSID, 5, 2) = 12
                   AND AUDITORID = 477';
      END LOOP;

     FORALL i IN 1 .. l_arr.COUNT
        INSERT INTO liquidationsdetails (....)
             VALUES (...);
  EXCEPTION
     WHEN DML_ERRORS
     THEN
        NULL;
  END;
  EXIT WHEN c%NOTFOUND;
END LOOP;   
CLOSE C;
COMMIT;
END;

我想在 oracle 批量 forall 收集循环中使用 select 语句将结果设置为数组变量。 在上面的代码中,我收到 [Error] Execution (60: 42): PLS-00487: Invalid reference to variable 'NUMBER' PL/SQL: Statement denied.

如果可能的话,我更喜欢在 forall 循环中使用 SELECT SUM () 语句。

有什么想法吗?

【问题讨论】:

  • 使用 into 子句而不使用 '=' 符号。
  • 您确定将一个 constant 字符串插入到变量中最多 500 次吗?
  • Tarun 我也改变了使用 into 子句:SELECT NVL (SUM (CURRPERIODVALUE), 0) INTO vprev (r).vPREVPERIODVALUE FROM LIQUIDATIONSDETAILS WHERE APPOINTOFCAID = l_arr (r).ID AND PROCESSID
  • Wernfried 我需要将选择结果插入字符串数组

标签: oracle plsql


【解决方案1】:

在问题的代码中,您尝试将字符串分配给数字表中的元素;在 cmets 中,您已对其进行了修改以选择数值,但是在两者中,您的表元素引用都错误;这个:

INTO vprev (r).vPREVPERIODVALUE

应该是:

INTO vprev (r)

vPREVPERIODVALUEvprev 的类型(并且是 TABLE OF NUMBER),因此您不要直接引用该类型。

在尝试为其元素分配值之前,您似乎也没有初始化或扩展该集合。

对游标循环的每次迭代都进行一次选择似乎很奇怪而且效率低下;您可以改为在光标中进行外部连接,例如:

CURSOR c
IS
    SELECT vcn.ID, vcn.OAUDITORID,
             NVL (SUM (CURRPERIODVALUE), 0) AS PREVPERIODVALUE
      FROM view_cost_noabc vcn
 LEFT JOIN LIQUIDATIONSDETAILS ld
        ON ld.APPOINTOFCAID = vcn.ID
       AND ld.AUDITORID = vcn.OAUDITORID
       AND ld.PROCESSID < vPROCSESSID
       AND SUBSTR (ld.PROCESSID, 5, 2) = 12
     WHERE vcn.OAUDITORID = 477 AND vcn.FL <> 'Ο' AND vcn.yearid < 2015
  GROUP BY vcn.ID, vcn.OAUDITORID
  ORDER BY vcn.ID;

那么您根本不需要vPREVPERIODVALUEvprev 或您的内部循环。您可能需要 view_cost_noabc 中的其他列进行插入 - 如果需要,请将它们添加到选择列表和 group-by 子句中。然后您可以参考l_arr(i).PREVPERIODVALUE 来查看相应的值,因为这仍然基于游标的行类型;我使用了左外连接,因为它看起来(基于NVL)就像您在LIQUIDATIONSDETAILS 中并不总是有匹配的记录。

您没有显示表格 DDL,但由于 vPROCSESSID 被声明为数字,因此 PROCESSID 很可能也是一个数字 - 在这种情况下使用 substr 很奇怪 - 你正在做一个隐式转换为字符串,并假设长度至少为 7 位。这可能对您和您的数据有意义,但看起来很奇怪。

目前forall 插入位于内部循环中,这不太可能是您真正想要的;但是如果你失去了内部循环,这个问题无论如何都会消失。

【讨论】:

  • Alex Poole 我不能使用内部联接。我需要将 view_cost_noabc 的一些记录插入到 LIQUIDATIONSDETAILS 中。我需要在 LIQUIDATIONSDETAILS 中检查是否已经插入了 indedified 记录,如果是,我需要获取旧记录的数量并将其放入新插入记录的先前值列中。
  • @Giorgos - 我使用了左外连接,而不是内连接;我假设(来自 nvl)您在 liquidationdetails 中可能没有任何匹配的记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 2015-01-28
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
相关资源
最近更新 更多