PL/SQL 为员工分配等级的程序

PL/SQL procedure to assign grades to the employees

create or replace procedure p2
as
    CURSOR c1 IS
      SELECT salary
      FROM   employee1
      FOR UPDATE;
BEGIN
FOR employee_rec IN c1 LOOP
exit when c1%notfound;
if salary>20000 then
update employee1 set grade='A' WHERE  CURRENT OF c1;
if salary>15000 then
update employee1 set grade='B' WHERE  CURRENT OF c1;
if salary>10000 then
update employee1 set grade='C' WHERE  CURRENT OF c1;
if salary<10000 then
update employee1 set grade='D' WHERE  CURRENT OF c1;
end if;
end if;
end if;
end if;
END LOOP;
END p2;

错误显示为薪水未申报我怎样才能使这段代码更好以获得所需的输出???

不是

if salary>20000 then

但是

if employee_rec.salary>20000 then

您编写的代码可以简化 - 最多只需要一个 UPDATE 语句。但是,如果您使用 PL/SQL 进行学习,CASE 可能是比嵌套 IF 更好的选择。类似于此示例的内容基于 Scott EMP table.

的子集

测试数据:

SQL> create table test as
  2    select empno, ename, sal, 'x' grade
  3    from emp
  4    where deptno = 10;

Table created.

SQL> select * from test order by sal desc;

     EMPNO ENAME             SAL G
---------- ---------- ---------- -
      7839 KING             5000 x
      7782 CLARK            2450 x
      7934 MILLER           1300 x

程序、测试和结果:

SQL> create or replace procedure p2 as
  2    cursor c1 is select sal from test for update;
  3  begin
  4    for employee_rec in c1 loop
  5      update test set
  6        grade = case when employee_rec.sal  > 3000 then 'A'
  7                     when employee_rec.sal  > 2000 then 'B'
  8                     when employee_rec.sal  > 1000 then 'C'
  9                     when employee_rec.sal <= 1000 then 'D'
 10                end
 11      where current of c1;
 12    end loop;
 13  end;
 14  /

Procedure created.

SQL> exec p2;

PL/SQL procedure successfully completed.

SQL> select * From test order by sal desc;

     EMPNO ENAME             SAL G
---------- ---------- ---------- -
      7839 KING             5000 A
      7782 CLARK            2450 B
      7934 MILLER           1300 C

SQL>

为什么不简单地这样:

update employee1 set grade= 
case 
   when salary>20000 then 'A'
   when salary>15000 then 'B'
   when salary>10000 then 'C'
   when salary<10000 then 'D'
   ELSE grade -- keep existing grade value
end;

你的错误是因为没有变量salary。您有一个名为 employee_rec 的游标,其中包含一个名为 salary 的列,但您需要使用 employee_rec.salary.

来引用它

如果我们修复它(并缩进您的代码)然后它会编译:

CREATE PROCEDURE p2 AS
  CURSOR c1 IS
    SELECT salary
    FROM   employee1
    FOR UPDATE;
BEGIN
  FOR employee_rec IN c1 LOOP
    EXIT WHEN c1%NOTFOUND;

    IF employee_rec.salary>20000 THEN
      update employee1 set grade='A' WHERE CURRENT OF c1;
      IF employee_rec.salary>15000 THEN
        update employee1 set grade='B' WHERE  CURRENT OF c1;
        IF employee_rec.salary>10000 THEN
          update employee1 set grade='C' WHERE  CURRENT OF c1;
          IF employee_rec.salary<10000 THEN
            update employee1 set grade='D' WHERE  CURRENT OF c1;
          END IF;
        END IF;
      END IF;
    END IF;
  END LOOP;
END p2;
/

但是,由于嵌套的 IF 语句,它不会为您提供所需的输出。如果将嵌套的 IF 语句替换为 ELSIF:

CREATE OR REPLACE PROCEDURE p2 AS
  CURSOR c1 IS
    SELECT salary
    FROM   employee1
    FOR UPDATE;
BEGIN
  FOR employee_rec IN c1 LOOP
    EXIT WHEN c1%NOTFOUND;

    IF employee_rec.salary>20000 THEN
      update employee1 set grade='A' WHERE CURRENT OF c1;
    ELSIF employee_rec.salary>15000 THEN
      update employee1 set grade='B' WHERE  CURRENT OF c1;
    ELSIF employee_rec.salary>10000 THEN
      update employee1 set grade='C' WHERE  CURRENT OF c1;
    ELSIF employee_rec.salary<10000 THEN
      update employee1 set grade='D' WHERE  CURRENT OF c1;
    END IF;
  END LOOP;
END p2;
/

那你的程序就可以了(工资是10000的时候除外)。

但是,您仍然可以通过删除游标来提高效率:

CREATE OR REPLACE PROCEDURE p2 AS
BEGIN
  UPDATE employee1
  SET grade = CASE
              WHEN salary > 20000 THEN 'A'
              WHEN salary > 15000 THEN 'B'
              WHEN salary > 10000 THEN 'C'
                                  ELSE 'D'
              END;
END p2;
/

db<>fiddle