仅使用for循环的程序,即没有游标或批量收集

时间:2012-10-10 06:45:55

标签: oracle plsql

我使用bulkcollect制作了这个程序。 现在,我想让另一个程序只使用for循环执行相同的任务,但不使用bulkcollect或游标。 请帮帮我,怎么做?

PROCEDURE PR_TRIAL_BAL_BULKWITHOUTCUR IS

    VAR_OF_TYP_TBL TYP_TBL;

  BEGIN
    SELECT * BULK COLLECT INTO VAR_OF_TYP_TBL 
      FROM (SELECT NAME, SUM(CREDIT) AS CREDIT, SUM(DEBIT) AS DEBIT
              FROM (SELECT (SELECT GL_NAME
                              FROM QM_GL
                             WHERE QM_GL.GL_ID = QT_ACCOUNTING.GL_ID) AS NAME,
                           DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                  'CR',
                                  (QT_ACCOUNTING.TRANS_AMOUNT),
                                  0.00) AS CREDIT,
                           DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                  'DR',
                                  (QT_ACCOUNTING.TRANS_AMOUNT),
                                  0.00) AS DEBIT

                      FROM QT_ACCOUNTING, QM_ACCOUNTING_PERIOD

                     WHERE QT_ACCOUNTING.VALUE_DATE BETWEEN
                           QM_ACCOUNTING_PERIOD.PERIODFROM AND
                           QM_ACCOUNTING_PERIOD.PERIODTO
                       AND QM_ACCOUNTING_PERIOD.STATUS = 'O')
             GROUP BY NAME);

    FOR I IN 1 .. VAR_OF_TYP_TBL.COUNT LOOP

      IF (VAR_OF_TYP_TBL(I).CREDIT - VAR_OF_TYP_TBL(I).DEBIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (VAR_OF_TYP_TBL(I).NAME,
           (VAR_OF_TYP_TBL(I).CREDIT - VAR_OF_TYP_TBL(I).DEBIT),
           0);
      END IF;
      IF (VAR_OF_TYP_TBL(I).DEBIT - VAR_OF_TYP_TBL(I).CREDIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (VAR_OF_TYP_TBL(I).NAME,
           0,
           (VAR_OF_TYP_TBL(I).DEBIT - VAR_OF_TYP_TBL(I).CREDIT));
      END IF;

    END LOOP;
    VAR_OF_TYP_TBL.DELETE;

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLERRM);
      BEGIN
        VAR_OF_TYP_TBL.DELETE;
      EXCEPTION
        WHEN OTHERS THEN
          NULL;
      END;
  END;

3 个答案:

答案 0 :(得分:1)

免责声明:此解决方案不建议使用,不应使用 我用它污染这个网站的唯一原因是因为这是OP想要的......
请不要低估这个答案

这是一个不在显式光标上的循环

 PROCEDURE PR_TRIAL_BALANCE_FORLOOP IS

 max_j    NUMBER;
 v_name   QM_GL.GL_NAME%TYPE;
 v_debit  NUMBER;
 v_credit NUMBER;

  BEGIN

  SELECT count(*)
    INTO max_j
    FROM (SELECT NAME, SUM(CREDIT) AS CREDIT, SUM(DEBIT) AS DEBIT
                  FROM (SELECT (SELECT GL_NAME
                                  FROM QM_GL
                                 WHERE QM_GL.GL_ID = QT_ACCOUNTING.GL_ID) AS NAME,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'CR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS CREDIT,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'DR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS DEBIT

                          FROM QT_ACCOUNTING, QM_ACCOUNTING_PERIOD

                         WHERE QT_ACCOUNTING.VALUE_DATE BETWEEN
                               QM_ACCOUNTING_PERIOD.PERIODFROM AND
                               QM_ACCOUNTING_PERIOD.PERIODTO
                           AND QM_ACCOUNTING_PERIOD.STATUS = 'O')
                 GROUP BY NAME);

  FOR j IN 1..max_j LOOP

    select tt.name, tt.credit, tt.debit  INTO v_name, v_credit, v_debit
     from (
      SELECT rownum rn, NAME, SUM(CREDIT) AS CREDIT, SUM(DEBIT) AS DEBIT
                             FROM (SELECT (SELECT GL_NAME
                                  FROM QM_GL
                                 WHERE QM_GL.GL_ID = QT_ACCOUNTING.GL_ID) AS NAME,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'CR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS CREDIT,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'DR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS DEBIT

                          FROM QT_ACCOUNTING, QM_ACCOUNTING_PERIOD

                         WHERE QT_ACCOUNTING.VALUE_DATE BETWEEN
                               QM_ACCOUNTING_PERIOD.PERIODFROM AND
                               QM_ACCOUNTING_PERIOD.PERIODTO
                           AND QM_ACCOUNTING_PERIOD.STATUS = 'O')
                 GROUP BY NAME ) tt
         where tt.rn = j;

      IF (v_CREDIT - v_DEBIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (v_NAME,
           (v_CREDIT - v_DEBIT),
           0);
      END IF;
      IF (v_DEBIT - v_CREDIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (v_NAME,
           0,
           (v_DEBIT - v_CREDIT));
      END IF;

  END LOOP; 

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLERRM);
  END;

请注意,这是一个非常糟糕的解决方案,它在循环上运行,每次只查询一条记录。这不是那种做事的方式,但这是满足您要求的方式

答案 1 :(得分:0)

您可以将其作为单个insert select执行:

INSERT INTO TBL_TRIAL_BALANCE_REPORT 
SELECT NAME
     , case when CREDIT > DEBIT then  CREDIT - DEBIT else 0 end
     , case when DEBIT > CREDIT then  DEBIT - CREDIT else 0 end
      FROM (SELECT NAME, SUM(CREDIT) AS CREDIT, SUM(DEBIT) AS DEBIT
              FROM (SELECT (SELECT GL_NAME
                              FROM QM_GL
                             WHERE QM_GL.GL_ID = QT_ACCOUNTING.GL_ID) AS NAME,
                           DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                  'CR',
                                  (QT_ACCOUNTING.TRANS_AMOUNT),
                                  0.00) AS CREDIT,
                           DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                  'DR',
                                  (QT_ACCOUNTING.TRANS_AMOUNT),
                                  0.00) AS DEBIT

                      FROM QT_ACCOUNTING, QM_ACCOUNTING_PERIOD

                     WHERE QT_ACCOUNTING.VALUE_DATE BETWEEN
                           QM_ACCOUNTING_PERIOD.PERIODFROM AND
                           QM_ACCOUNTING_PERIOD.PERIODTO
                       AND QM_ACCOUNTING_PERIOD.STATUS = 'O')
             GROUP BY NAME);

答案 2 :(得分:0)

 PROCEDURE PR_TRIAL_BALANCE_FORLOOP IS

 I NUMBER(6):=0;

  BEGIN

  FOR I IN (SELECT NAME, SUM(CREDIT) AS CREDIT, SUM(DEBIT) AS DEBIT
                  FROM (SELECT (SELECT GL_NAME
                                  FROM QM_GL
                                 WHERE QM_GL.GL_ID = QT_ACCOUNTING.GL_ID) AS NAME,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'CR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS CREDIT,
                               DECODE(QT_ACCOUNTING.TRANS_TYPE,
                                      'DR',
                                      (QT_ACCOUNTING.TRANS_AMOUNT),
                                      0.00) AS DEBIT

                          FROM QT_ACCOUNTING, QM_ACCOUNTING_PERIOD

                         WHERE QT_ACCOUNTING.VALUE_DATE BETWEEN
                               QM_ACCOUNTING_PERIOD.PERIODFROM AND
                               QM_ACCOUNTING_PERIOD.PERIODTO
                           AND QM_ACCOUNTING_PERIOD.STATUS = 'O')
                 GROUP BY NAME)
  LOOP

   IF (I.CREDIT - I.DEBIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (I.NAME,
           (I.CREDIT - I.DEBIT),
           0);
      END IF;
      IF (I.DEBIT - I.CREDIT) > 0 THEN
        INSERT INTO TBL_TRIAL_BALANCE_REPORT
        VALUES
          (I.NAME,
           0,
           (I.DEBIT - I.CREDIT));
      END IF;

  END LOOP;  

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLERRM);
  END;