我需要更新部门40和70的员工工资。部门40的所有员工将增加10%,而部门70的员工将增加15%。
我有一名来自70部门的员工,他的薪水是10000,所以他会增加15%。我希望他的薪水能够达到11500,但却变成了13225.我无法理解为什么。 40部门的员工有正确的加薪,只有部门70的员工错误。
这是pl / sql块..
SET serveroutput ON
DECLARE
CURSOR cur_emp
IS
SELECT * FROM employees WHERE department_id = 40 OR department_id = 70;
rec_emp cur_emp%rowtype;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO rec_emp;
IF rec_emp.department_id = 40 THEN
UPDATE employees
SET salary = salary + (salary * 0.1)
WHERE employee_id = rec_emp.employee_id;
elsif rec_emp.department_id = 70 THEN
UPDATE employees
SET salary = salary + (salary * 0.15)
WHERE employee_id = rec_emp.employee_id;
END IF;
EXIT
WHEN cur_emp%notfound;
END LOOP;
CLOSE cur_emp;
END;
/
有人能帮我解决这个问题吗?感谢
答案 0 :(得分:4)
无需存储过程:
update employees
set salary = case
when department_id = 40 then salary * 1.10
when department_id = 70 then salary * 1.15
else salary -- not strictly necessary. just to make sure.
end
where department_id in (40,70);
如果你坚持这样做,使用UPDATE ... WHERE CURRENT OF
的缓慢方式(PL / SQL中的循环)可能比“无关”更新更快。
你的代码真正的问题是你要离开循环“太晚了”。即使光标在获取后没有返回任何内容,您仍然会进行更新。您应该将EXIT WHEN ...
放在之前的IF子句和更新。
DECLARE
CURSOR cur_emp
IS
SELECT * FROM employees WHERE department_id = 40 OR department_id = 70;
rec_emp cur_emp%rowtype;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO rec_emp;
EXIT WHEN cur_emp%notfound; -- **** leave the loop right here, BEFORE doing the update *****
IF rec_emp.department_id = 40 THEN
UPDATE employees
SET salary = salary + (salary * 0.1)
WHERE employee_id = rec_emp.employee_id;
elsif rec_emp.department_id = 70 THEN
UPDATE employees
SET salary = salary + (salary * 0.15)
WHERE employee_id = rec_emp.employee_id;
END IF;
END LOOP;
CLOSE cur_emp;
END;
/
更有效的方法是使用可更新的游标:
DECLARE
CURSOR cur_emp
IS
SELECT department_id, salary
FROM employees
WHERE department_id in (40,70)
FOR UPDATE OF salary;
rec_emp cur_emp%rowtype;
new_sal number(12,2);
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO rec_emp;
EXIT WHEN cur_emp%NOTFOUND;
IF rec_emp.department_id = 40 THEN
new_sal := rec_emp.salary * 1.10;
elsif rec_emp.department_id = 70 THEN
new_sal := rec_emp.salary * 1.15;
END IF;
UPDATE employees
SET salary = new_sal
WHERE CURRENT OF cur_emp;
END LOOP;
CLOSE cur_emp;
END;
/
WHERE CURRENT OF
的使用实际上会更清楚地揭示错误,因为如果您在之后放置invalid rowid
,则循环将失败exit
更新