为啥我在 PL/SQL 中的 for 循环没有打印出最后一次迭代

Posted

技术标签:

【中文标题】为啥我在 PL/SQL 中的 for 循环没有打印出最后一次迭代【英文标题】:why is my for loop in PL/SQL not printing out the last iteration为什么我在 PL/SQL 中的 for 循环没有打印出最后一次迭代 【发布时间】:2014-04-26 22:21:49 【问题描述】:

我正在创建一个获取费用编号的 PL/SQL 脚本,然后它获取用于费用的现金总额、用于购买的信用额度、费用总额和支付的总额。我正在使用 FOR 循环来为表中的每个 expnum 完成此操作。获得这些值后,它会查看 totalPaid 是否小于或等于总费用。当我的循环运行时,它会输出 expNum 1 到 4 的信息,即使我的表中有 5 个。我无法弄清楚为什么脚本没有运行 5 次并且在第 4 次执行后停止。下面是我的脚本。非常感谢任何提示/帮助,谢谢。

DECLARE
  lineTotal NUMBER;
  cashPaid NUMBER;
  creditPaid NUMBER;
  totalPaid NUMBER;
  expNumMax NUMBER;
BEGIN
  SELECT MAX(EXPNUM)
    INTO expNumMax
    FROM EXPDET;

  dbms_output.put_line ('EXP num max is: ' || expNumMax);

  FOR expNumCounter IN 1..expNumMax
  LOOP
    SELECT SUM(Amt)
      INTO lineTotal
      FROM EXPDET
      WHERE ExpNum = expNumCounter;

    SELECT CASHAMT
      INTO cashPaid
      FROM EXPMAST
      WHERE ExpNum = expNumCounter;

    SELECT SUM(Amt)
      INTO creditPaid
      FROM ExpByCc
      WHERE ExpNum = expNumCounter;

    totalPaid := cashPaid + creditPaid;

    IF totalPaid < lineTotal THEN
      dbms_output.put_line ('SELECT * FROM expmast');
    END IF;

    IF totalPaid = lineTotal THEn
      dbms_output.put_line ('EXPNUM is: ' || expNumCounter);
      dbms_output.put_line ('Line Total is: '|| lineTotal);
      dbms_output.put_line ('cashPaid is: ' || cashPaid);
      dbms_output.put_line ('Credit Paid is: '|| creditPaid);
      dbms_output.put_line ('Total paid is: ' || totalPaid);
    END IF;
  END LOOP;
END;
/

【问题讨论】:

也许您的表中有重复的 EXPNUM 值,或者这些值从 0 而不是 1 开始。此外,您可能可以使用分析函数做您想做的事情,但这样会更容易知道您是否提供了示例数据和所需的输出。 如果您没有连续的一系列 expnum 值,您的代码也会失败 - 即这些数字之间的差距。首先,循环内的第二个选择将获得no_data_found 的不存在值。如果您确实想在循环中执行此操作作为练习,您可以将所有 expnum 值批量选择到一个集合中并对其进行迭代。但这仍然不是查看这些数据的最有效方式。 您可能需要考虑在 EXPDET 表上使用游标 FOR 循环,而不是使用值 FOR 循环。根据我的经验,价值 FOR 循环在 PL/SQL 中几乎没有用处,而游标 FOR 循环是该语言的基础。 YMMV。分享和享受。 正如已经讨论过的,肯定有更好的方法来解决这个问题,但也许你在最后一行有totalPaid &gt; lineTotal?在这种情况下,你不会写任何东西...... 【参考方案1】:

只要您在 EXPDET 中没有太多记录,您就会耗尽内存,下面的代码应该可以满足您的要求。

(注意:我没有运行代码,因为我没有你的数据结构)

DECLARE
  CURSOR c_EXPDET IS
    SELECT EXPNUM
      INTO expNumMax
      FROM EXPDET
    ;
  TYPE t_EXPDET IS TABLE OF c_EXPDET%ROWTYPE INDEX BY PLS_INTEGER;  
  l_EXPDET t_EXPDET;

  l_cur NUMBER;

  lineTotal NUMBER;
  cashPaid NUMBER;
  creditPaid NUMBER;
  totalPaid NUMBER;
  expNumMax NUMBER;
BEGIN
  OPEN c_EXPDET;
  FETCH c_EXPDET BULK COLLECT INTO l_EXPDET;
  CLOSE c_EXPDET;

  l_cur := l_EXPDET.FIRST;
  WHILE (l_cur IS NOT NULL) LOOP
        SELECT SUM(Amt)
          INTO lineTotal
          FROM EXPDET
          WHERE ExpNum = l_EXPDET(l_cur);

        SELECT CASHAMT
          INTO cashPaid
          FROM EXPMAST
          WHERE ExpNum = l_EXPDET(l_cur);

        SELECT SUM(Amt)
          INTO creditPaid
          FROM ExpByCc
          WHERE ExpNum = l_EXPDET(l_cur);

        totalPaid := cashPaid + creditPaid;

        IF totalPaid < lineTotal THEN
          dbms_output.put_line ('SELECT * FROM expmast');
        END IF;

        IF totalPaid = lineTotal THEN
          dbms_output.put_line ('EXPNUM is: ' || l_EXPDET(l_cur));
          dbms_output.put_line ('Line Total is: '|| lineTotal);
          dbms_output.put_line ('cashPaid is: ' || cashPaid);
          dbms_output.put_line ('Credit Paid is: '|| creditPaid);
          dbms_output.put_line ('Total paid is: ' || totalPaid);
        END IF;

        l_cur := l_EXPDET.NEXT(l_cur);
  END LOOP; --Loop through EXPDET  

END;
/

【讨论】:

以上是关于为啥我在 PL/SQL 中的 for 循环没有打印出最后一次迭代的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们不需要在 pl sql 的 for 循环中打开和获取显式游标?

Oracle PL/SQL 中的 for 循环后变量丢失值

for循环后的最后一个过程语句在pl sql中不起作用

PL/SQL 中的 for 循环和列

如何使用pl sql中的匿名块打印出整个表?

oracle 11g 中 for 循环中的 PL/SQL 限制