PLSQL插入For循环

时间:2019-03-27 12:02:09

标签: oracle plsql

我有一个PL / SQL脚本可以从另一个表插入数据,但是结果却不符合我的预期。 BBB表中的插入仅保存d_rec循环的第一行。当我尝试在另一个sql中打印/输出d-Rec时,它给了我保存在yyy表中的所有行。

我已经尝试过使用游标,但是结果仍然相同。

DECLARE
GROUP_SEQ NUMBER;
TRANS_SEQ NUMBER;
ID NUMBER;
PP NUMBER := 1;
TRANS_ID NUMBER;
TRANS_SUM NUMBER;
UNIT VARCHAR(6);
DEBET NUMBER;
CREDIT NUMBER;

BEGIN
FOR v_rec in (SELECT unit from xxx)
LOOP
   FOR d_rec in (SELECT ID, TRANS_SUM, UNIT from yyy where unit = v_rec.unit )
   LOOP

     UPDATE YYY_SEQUENCE 
       SET SEQ_COUNT = SEQ_COUNT + 1
       WHERE SEQ_NAME = 'GROUP_SEQ'
       RETURNING SEQ_COUNT 
       INTO GROUP_SEQ;
       COMMIT;

      INSERT INTO AAA (ID, SEQ) VALUES (ID, GROUP_SEQ);
      WHILE PP <= 4
      LOOP
         UPDATE YYY_SEQUENCE 
         SET SEQ_COUNT = SEQ_COUNT + 1
         WHERE SEQ_NAME = 'TRANS_SEQ'
         RETURNING SEQ_COUNT 
         INTO TRANS_SEQ;
         COMMIT;

         IF (PP < 3) THEN
             DEBET := TRANS_SUM;
             CREDIT := 0;
         ELSE             
             DEBET := 0;
             CREDIT := TRANS_SUM;
         END IF;
         PP := PP +1;
         INSERT INTO BBB(ID, SEQ, UNIT, DEBET, CREDIT) VALUES (ID, TRANS_SEQ, UNIT, DEBET, CREDIT);
         COMMIT;
      END LOOP;
   END LOOP;
PP :=1;
END LOOP;
END

第一次插入为我提供了d_rec数据中的所有行。但是第二次插入只给我第一行d_rec数据。

1 个答案:

答案 0 :(得分:0)

要在PP循环内的d_rec循环之后重置v_rec计数器;这意味着,一旦将一个单元的第一个d_rec的值增加到4,随后的d_rec迭代将跳过最内层的循环-因为PP <= 4永远都不适用。

一种快速的解决方法是在循环中移动该重置:

...
      END LOOP;
      -- reset PP after this loop
      PP :=1;
   END LOOP;
   -- instead of after this loop
   --PP :=1;
END LOOP;
END

但是如果您在使用它之前立即进行重置,可能会很清楚:

...
      INSERT INTO AAA (ID, SEQ) VALUES (ID, GROUP_SEQ);
      -- reset here
      PP := 1;
      WHILE PP <= 4
      LOOP
         PP := PP +1;

         ...

         IF (PP < 3) THEN
             DEBET := TRANS_SUM;
             CREDIT := 0;
         ELSE             
             DEBET := 0;
             CREDIT := TRANS_SUM;
         END IF;

         INSERT INTO BBB(ID, SEQ, UNIT, DEBET, CREDIT) VALUES (ID, TRANS_SEQ, UNIT, DEBET, CREDIT);
         COMMIT;
      END LOOP;
   END LOOP;
END LOOP;
END

或者完全摆脱显式变量-从而无需声明,重置或递增-而是使用a for loop

...
      INSERT INTO AAA (ID, SEQ) VALUES (ID, GROUP_SEQ);
      FOR PP IN 1..4
      LOOP
         ...

         IF (PP < 3) THEN
             DEBET := TRANS_SUM;
             CREDIT := 0;
         ELSE             
             DEBET := 0;
             CREDIT := TRANS_SUM;
         END IF;

         INSERT INTO BBB(ID, SEQ, UNIT, DEBET, CREDIT) VALUES (ID, TRANS_SEQ, UNIT, DEBET, CREDIT);
         COMMIT;
      END LOOP;
   END LOOP;
END LOOP;
END

偶然地,所有这些提交看起来都是错误的-它们使无法在失败时重新启动,但也对性能造成不利影响。您可能可以将其简化为更少的循环。