【问题标题】:PL/SQL block with %ROWCOUNT compiles but doesn't output result带有 %ROWCOUNT 的 PL/SQL 块编译但不输出结果
【发布时间】:2020-11-23 05:46:37
【问题描述】:

我正在尝试打印信用额度最高的前 3 条记录。我的代码可以编译,但尽管有SET SERVEROUTPUT ON SIZE 100000,但没有打印任何东西,我对此有点困惑。该表显示没有问题。另外,当我只有

EXIT WHEN high_credit%ROWCOUNT > 4;

脚本进入无限循环。

代码:

SET SERVEROUTPUT ON SIZE 1000000

DECLARE
   CURSOR high_credit IS
   SELECT first_name, last_name, employee_id, credit_limit FROM employees
      ORDER BY credit_limit DESC;   
   emp_fname employees.first_name%TYPE;
   emp_lname employees.last_name%TYPE;
   emp_empno employees.employee_id%TYPE;
   emp_crd_lmt employees.credit_limit%TYPE;
BEGIN
   DBMS_OUTPUT.PUT_LINE('First_Name ' || 'Last_Name ' || 'Employee_Id '
 || 'Credit_Limit');
   OPEN high_credit;
   LOOP
      FETCH high_credit INTO emp_fname, emp_lname, emp_empno, emp_crd_lmt;
      EXIT WHEN (high_credit%ROWCOUNT > 4) OR (high_credit%NOTFOUND);     
      DBMS_OUTPUT.PUT_LINE(emp_fname || ' ' || emp_lname || ' ' || emp_empno
 || ' ' || emp_crd_lmt);
   END LOOP;
   CLOSE high_credit;
END;

CREATE TABLE employees (
    employee_id NUMBER(3) NOT NULL,
    first_name VARCHAR2(8) NOT NULL,
    last_name VARCHAR2(15) NOT NULL,
    credit_limit NUMBER(4,2) NOT NULL,    
    CONSTRAINT employee_id_pk PRIMARY KEY (employee_id)    
);

INSERT INTO employees VALUES (201, 'Susan', 'Brown', 30);
INSERT INTO employees VALUES (202, 'Jim', 'Kern', 25);
INSERT INTO employees VALUES (203, 'Martha', 'Woods', 25);
INSERT INTO employees VALUES (204, 'Ellen', 'Owens', 15);
INSERT INTO employees VALUES (205, 'Henry', 'Perkins', 25);

代码在 COMMIT 之后工作;在 INSERT... 上按照建议:

【问题讨论】:

  • 这不是 %rowcount 的使用方式。 %rowcount 返回使用 DML 修改的行数。
  • @OldProgrammer,%rowcount 确实适用于 select 语句,在这里它将返回最后获取的行数。您将得到 1 或 0。如果是批量收集,那么您可以返回更高的值。请参阅文档docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/…
  • COMMIT 后生效;在插入;

标签: oracle plsql rowcount


【解决方案1】:

除了SQL%ROWCOUNT的无效使用(正如OldProgrammer所说)(虽然它不会影响你的问题),看起来你

  • 在 SQL Developer 中创建表并插入行
  • 没有提交
  • 在 SQL*Plus 中执行了您的 PL/SQL 脚本
  • 由于未提交插入,SQL*Plus 会话看不到这些行(但它会将表视为CREATE TABLE 是一个 DDL)

因此

  • COMMIT 在 SQL Developer 中
  • 然后在 SQL*Plus 中运行您的代码

关于你在评论中提到的任务:看看这是否有帮助(我没有你的桌子,所以我使用 Scott 的 EMP):

SQL> set serveroutput on;
SQL> declare
  2    cursor c1 is
  3      select * from emp
  4      order by sal desc;
  5    c1r c1%rowtype;
  6  begin
  7    open c1;
  8    loop
  9      fetch c1 into c1r;
 10      exit when c1%notfound or c1%rowcount > 3;
 11
 12      dbms_output.put_line(c1%rowcount ||': '|| c1r.ename ||': '|| c1r.sal);
 13    end loop;
 14    close c1;
 15  end;
 16  /
1: KING: 5001
2: FORD: 3000
3: SCOTT: 3000

PL/SQL procedure successfully completed.

SQL>

【讨论】:

  • 都是 SQL Developer,但是,是的,我需要一个 COMMIT 来让它工作。这就是我想到使用 %ROWCOUNT 的地方:docs.oracle.com/cd/A97630_01/appdev.920/a96624/a_samps.htm#563 (Sample2)
  • 顺便说一句,既然我的代码可以按我的预期工作,你介意分享一下如果你必须要如何编写代码:“创建一个 PL/SQL 块来获取和显示信用额度最高的三名员工。对输出进行排序,以便首先显示信用额度最高的员工。使用 %ROWTYPE 和显式光标属性 %ROWCOUNT。"
  • 感谢代码示例。在我的示例中,我还必须处理包含 NULL 值的行(在您的情况下为 sal 列)。在这些情况下,构造“c1%notfound 时退出”是否也足够了?我问这个是因为我后来还在 Cursor 声明中的代码中添加了一个逻辑结构 WHERE sal IS NOT NULL (您的示例)。它适用于我的代码。
  • WHERE 子句更有意义,我想说。一旦游标返回它拥有的所有行,EXIT 子句将负责退出循环。没有它,你最终会陷入无限循环。
猜你喜欢
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 2016-10-03
  • 1970-01-01
  • 2019-02-16
相关资源
最近更新 更多