Kat*_*ine 2 sql database plsql updating
我需要更新部门 40 和 70 员工的工资。部门 40 的所有员工都会加薪 10%,而部门 70 的员工都会加薪 15%。
我有 1 名来自 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;
/
Run Code Online (Sandbox Code Playgroud)
谁能帮我解决这个问题吗?谢谢
小智 5
不需要存储过程:
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);
Run Code Online (Sandbox Code Playgroud)
如果您坚持以慢速方式(PL/SQL 中的循环)执行此操作,则使用 anUPDATE ... WHERE CURRENT OF可能会比“不相关”更新更快。
您的代码的真正问题是您“太晚”离开循环。即使游标在获取后没有返回任何内容,您仍然会执行更新。您应该将 放在IF 子句和更新EXIT WHEN ... 之前。
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;
/
Run Code Online (Sandbox Code Playgroud)
更有效的方法是使用可更新游标:
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;
/
Run Code Online (Sandbox Code Playgroud)
实际上,使用会更清楚地揭示错误,因为如果您将 放在更新之后,WHERE CURRENT OF循环将失败并显示。invalid rowidexit