PL / SQL процедура присвоения оценок сотрудникам - PullRequest
0 голосов
/ 31 марта 2020
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;

Ошибка отображается как Зарплата не объявлена ​​ Как сделать этот код лучше, чтобы получить желаемый результат ???

Ответы [ 3 ]

2 голосов
/ 31 марта 2020

Почему бы просто не так:

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;
0 голосов
/ 31 марта 2020

Ваша ошибка из-за отсутствия переменной 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;
/

Тогда ваша процедура сработает (за исключением случаев, когда зарплата составляет 10 000).

Однако вы все равно можете сделать ее более эффективен, избавившись от курсора:

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;
/

дБ <> скрипка

0 голосов
/ 31 марта 2020

Это не

if salary>20000 then

, а

if employee_rec.salary>20000 then

Код, который вы написали, может быть упрощен - до одного UPDATE оператора. Однако, если вы используете PL / SQL для обучения, CASE, вероятно, лучший вариант, чем вложенные IF s. Примерно как этот пример, основанный на подмножестве таблицы EMP Скотта.

Данные испытаний:

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>
...