PlSql 陷入死循环

问题描述 投票:0回答:2

我有一个包含 7 列员工信息的表格,如下所示,但行数更多,并且会随着新员工的到来而增加更多。

emp_numb 薪水 部门编号
0001 111111 10 细胞 2 细胞 1 细胞 2 细胞 1
0002 222222 20 细胞 2 细胞 1 细胞 2 细胞 1
0003 333333 30 细胞 2 细胞 1 细胞 2 细胞 1
0004 444444 10 细胞 2 细胞 1 细胞 2 细胞 1

我正在尝试编写一个 plsql 程序,以便可以向我显示每个部门薪水最低的 2 名员工(如果以后我添加更多部门编号,则需要能够使用此程序)。 问题是,到目前为止我编写的代码,我陷入了无限循环并且无法理解我到目前为止失败的地方。如果问题不大,因为我对 sql 有点陌生,而且我的知识并不丰富,谁能检查我的代码并告诉我我在哪里失败了?提前致谢!

我的代码如下:

create or replace procedure lowemployees
as
cursor cur1 is select * from emple order by dept_no,salario;
empleadus emple%rowtype;
i number;
depcursor emple.dept_no%type;
depcompare emple.dept_no%type;
begin
i:=0;
open cur1;
fetch cur1 into empleadus;
depcursor:=empleadus.dept_no;
depcompare:=depcursor+1;
while cur1%found loop
while i<2 loop
dbms_output.put_line(empleadus.emp_no||'|'||empleadus.nombre||'|'||empleadus.oficio||'|'||empleadus.salario||'|'||empleadus.dept_no);
i:=i+1;
fetch cur1 into empleadus;
end loop;
depcursor:=empleadus.dept_no;
depcompare:=depcursor+1;
while depcursor<depcompare loop
fetch cur1 into empleadus;
i:=0;
depcursor:=empleadus.dept_no;
end loop;
dbms_output.put_line(empleadus.emp_no||'|'||empleadus.nombre||'|'||empleadus.oficio||'|'||empleadus.salario||'|'||empleadus.dept_no);
depcompare:=depcursor+1;
fetch cur1 into empleadus;
end loop;
close cur1;
end lowemployees;
sql oracle plsql sqlplus
2个回答
0
投票

如果你用缩进格式化你的代码,你会取得更好的成功。这是我添加意图后的内容:

create or replace procedure lowemployees
as
  cursor cur1 is 
    select * from emple order by dept_no,salario;
  empleadus emple%rowtype;
  i number;
  depcursor emple.dept_no%type;
  depcompare emple.dept_no%type;
begin
  i:=0;
  
  open cur1;
  fetch cur1 into empleadus;
  
  depcursor:=empleadus.dept_no;
  depcompare:=depcursor+1;
  
  while cur1%found loop
    while i<2 loop
      dbms_output.put_line(empleadus.emp_no||'|'||empleadus.nombre||'|'||empleadus.oficio||'|'||empleadus.salario||'|'||empleadus.dept_no);
      i:=i+1;
      
      fetch cur1 into empleadus;
    end loop;
    
    depcursor:=empleadus.dept_no;
    depcompare:=depcursor+1;
    
    while depcursor<depcompare loop
      fetch cur1 into empleadus;
      
      i:=0;
      depcursor:=empleadus.dept_no;
    end loop;
    
    dbms_output.put_line(empleadus.emp_no||'|'||empleadus.nombre||'|'||empleadus.oficio||'|'||empleadus.salario||'|'||empleadus.dept_no);
    depcompare:=depcursor+1;
    
    fetch cur1 into empleadus;
  end loop;
  
  close cur1;
end lowemployees;

您的主游标循环中有多个内部循环,并且您正在内部循环中获取。最后,每个外部游标循环仅获取一次。您还有一个没有明确退出条件的循环:

while depcursor<depcompare loop
  fetch cur1 into empleadus;

  i:=0;
  depcursor:=empleadus.dept_no;
end loop;

这是进入无限循环的简单方法。您不能确定 dept_no 会小于任何值。这是您无法控制的数据值。您需要使用更谨慎的退出条件。

但我也建议您重新考虑您对 PL/SQL 的使用。您的需求是用普通的旧 SQL 做的非常简单的事情。不需要程序代码和所有这些嵌套循环:

SELECT *
  FROM (SELECT e.*,
               ROW_NUMBER() OVER (PARTITION BY dept_no ORDER BY salario) rnk
          FROM emple e)
 WHERE rnk <= 2

0
投票

您可以为此使用通用表表达式。不需要光标。下面的查询将从每个部门中选择薪水最低的两名员工。

with minEmpSalary as
(select emp_numb,salary,dept_num,etc,row_number()over(partition by dept_num order by salary)rn from employees 
)
select emp_numb,salary,dept_num,etc from minEmpSalary where rn<=2
© www.soinside.com 2019 - 2024. All rights reserved.