我有一个包含 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;
如果你用缩进格式化你的代码,你会取得更好的成功。这是我添加意图后的内容:
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
您可以为此使用通用表表达式。不需要光标。下面的查询将从每个部门中选择薪水最低的两名员工。
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