oracle在oracle bulk forall collect循环中添加select语句

时间:2015-09-03 07:36:53

标签: oracle plsql

我有以下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 bulk forall collect循环中的select语句将结果设置为数组变量。 在上面的代码中,我收到[错误]执行(60:42):PLS-00487:对变量'NUMBER'PL / SQL的无效引用:语句被忽略。

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

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

在问题的代码中,您尝试将字符串分配给数字表中的元素;在你已经修改过的注释中选择一个数值,但是你们两个都没有表格元素引用错误;这样:

INTO vprev (r).vPREVPERIODVALUE

应该是:

INTO vprev (r)

vPREVPERIODVALUE类型为vprev(并且为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来查看相应的值,因为它仍然基于游标的rowtype;并且我使用了左外连接,因为它看起来(基于NVL),就像你在LIQUIDATIONSDETAILS中不会总是有匹配的记录。

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

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