oracle Pl/sql未运行所有if语句

ycggw6v2  于 2022-12-18  发布在  Oracle
关注(0)|答案(4)|浏览(181)

我的脚本需要执行以下操作
如果部门是10,工资高于2000给予6%的加薪,否则给7%的加薪。2如果部门是20,工资高于2500,给5%的加薪,否则给5.5%的加薪。
但是程序并没有运行完我所有的if语句,它停在了第一个if语句上,我不确定我还能用什么其他逻辑让它运行完所有的if语句。

SET SERVEROUTPUT ON

DECLARE
v_newsal emp.sal%TYPE;
v_sal emp.sal%TYPE;
v_deptno emp.deptno%TYPE;
CURSOR raise_cursor IS
  SELECT sal, deptno
    FROM emp;

BEGIN
OPEN raise_cursor;
fetch raise_cursor INTO v_sal, v_deptno;
LOOP
 IF v_deptno = 10 AND v_sal > 2000 THEN
   v_newsal := v_sal * 1.060;

 ELSE
  v_newsal := v_sal * 1.070;

 IF v_deptno = 20 AND v_sal > 2500 THEN
  v_newsal := v_sal * 1.050;

 ELSE
  v_newsal := v_sal * 1.055;

 END IF;
 END IF;

UPDATE emp SET
sal = v_newsal
WHERE deptno = v_deptno;

 EXIT;
END LOOP;
CLOSE raise_cursor;

END;
/
SET SERVEROUTPUT OFF

我试过elsif语句和嵌套的if语句,只是常规的if else语句,但似乎都不起作用。

px9o7tmv

px9o7tmv1#

问题是您要打开游标,读取一行,然后启动一个循环,在第一个循环结束时退出。
处理此类游标的常用方法是:打开游标,开始循环,读取行,如果找不到行则退出循环,如果找到行则继续执行其余的逻辑,然后返回到循环的开头并重复。
我假设您的过程是处理游标的学习练习的一部分,因为在真实的生活中,您最好像@Littlefoot在他们的回答中建议的那样,在单个update语句中处理逻辑。
在此基础上,您的代码应该如下所示:

<snip>
OPEN raise_cursor;
LOOP
  fetch raise_cursor INTO v_sal, v_deptno;
  EXIT WHEN raise_cursor%NOTFOUND;

  <your logic>
END LOOP;
CLOSE raise_cursor;
<snip>

注意:游标for循环(for <record> in <cursor> loop <logic> end loop;)编写起来更简单、更清晰,而且还具有内置优化功能,可以将逐行处理转换为批量行处理。它为您处理游标的打开、获取和退出,因此您无需担心它。然而,正如我所说的,我假设您正在学习如何显式地处理游标周围的打开、循环等操作。
另外,看看if语句的逻辑,它也没有意义:
如果部门是10,工资高于2000给予6%的加薪,否则给7%的加薪。2如果部门是20,工资高于2500,给5%的加薪,否则给5.5%的加薪。
第一个“else”子句只与第10部门有关吗?与第20部门也一样吗?您当前的逻辑意味着,如果您在第20部门的工资低于2500美元,或者在任何其他部门,您将从第一个查询中获得6%的加薪,然后在此基础上获得5.5%的加薪(对员工来说是甜蜜的交易,对雇主来说不是那么多!)
如果我对逻辑的理解是正确的,它应该是这样的:

IF v_deptno = 10 AND v_sal > 2000 THEN
  v_newsal := v_sal * 1.060;

ELSIF v_deptno = 10 THEN
  v_newsal := v_sal * 1.070;

ELSIF v_deptno = 20 AND v_sal > 2500 THEN
  v_newsal := v_sal * 1.050;

ELSIF v_deptno = 20 THEN -- maybe this clause should remain as the `ELSE` clause, if it applies to all other departments, etc
  v_newsal := v_sal * 1.055;

END IF

;

fslejnso

fslejnso2#

您可以使用单个UPDATE语句,使用WHERE子句仅更新特定部门中的员工,使用CASE表达式将不同的部门/薪金范围Map到加薪百分比:

UPDATE emp
SET sal = sal * CASE
                WHEN deptno = 10 AND sal > 2000 THEN 1.06
                WHEN deptno = 10                THEN 1.07
                WHEN deptno = 20 AND sal > 2500 THEN 1.05
                WHEN deptno = 20                THEN 1.055
                END
WHERE deptno IN (10,20)
qv7cva1a

qv7cva1a3#

也许是这样的

IF v_deptno = 10 THEN
   IF v_sal > 2500 THEN
       v_newsal := v_sal * 1.060;
   ELSE
       v_newsal := v_sal * 1.070;
   END IF;
END IF;
 
IF v_deptno = 20 THEN
   IF v_sal > 2500 THEN
      v_newsal := v_sal * 1.050;
   ELSE
      v_newsal := v_sal * 1.055;
   END IF;
END IF;
dgiusagp

dgiusagp4#

实际上,您不需要在循环中进行低效的逐行处理;将单个update语句与case表达式一起使用:

update emp set
  sal = case when deptno = 10 then 
                  case when sal > 2000 then sal * 1.060
                       else sal * 1.070
                  end
             when deptno = 20 then
                  case when sal > 2500 then sal * 1.050
                       else sal * 1.055
                  end
             else sal
        end;

相关问题