跳过记录并使用以前的记录数据

时间:2014-01-14 08:12:48

标签: sql oracle

问题: 编写一个PL / SQL块,根据以下标准为每个员工提供加薪: 保存为q3.sql不需要测试脚本。 •低于1000的员工获得6%的加薪 •1000至3000人的员工人数增加8% •员工人数超过3000人的人数增加12% 每次加注时,使用dbms_output打印消息“,你刚刚获得n%加薪,你的新工资是”。当所有加注完成后,回滚交易并打印消息,“他,他,他......开个玩笑!”

它执行正确的计算并返回没有错误,尽管它在前一个记录上进行计算然后跳过下一个记录。

SET SERVEROUTPUT ON
DECLARE
CURSOR sal_cursor IS
    SELECT ename, sal
     FROM EMP
FOR UPDATE OF sal NOWAIT;
    V_sal   emp.sal%TYPE;
    V_ENAME EMP.Ename%TYPE;
BEGIN
    FOR emp_record IN sal_cursor
LOOP
    FETCH sal_cursor INTO V_Ename, V_Sal;
    IF (V_SAL <= 1000) THEN
        UPDATE emp
        SET EMP.sal = (emp_record.sal * 1.06)
        WHERE CURRENT OF sal_cursor;
        v_sal := v_sal * 1.06;
    ELSIF V_SAL > 1000 AND V_sal <= 3000 THEN 
        UPDATE emp
        SET EMP.sal = (emp_record.sal * 1.08)
        WHERE CURRENT OF sal_cursor;
        v_sal := v_sal * 1.08;
    ELSE
        UPDATE emp
        SET EMP.sal = (emp_record.sal * 1.12)
        WHERE CURRENT OF sal_cursor;
        v_sal := v_sal * 1.12;
    END IF;
    DBMS_OUTPUT.PUT_LINE(V_ENAME || ', you just got an n percent raise
    and your new salary is ' || v_sal);
END LOOP;
DBMS_OUTPUT.PUT_LINE('He, he, he... just kidding!');
ROLLBACK;
END;

2 个答案:

答案 0 :(得分:0)

FOR语句已从光标中提取记录。所以不要在以下行中执行FETCH。

答案 1 :(得分:0)

您正在混淆two ways of handling cursors - 显式和隐式CURSOR FOR循环。您可以比较从该语法页面链接的示例。

FOR emp_record IN sal_cursor方法会自动将每一行提取到emp_record变量中。然后,您明确的FETCH会读取 next 记录。 (我有点惊讶它并没有抱怨它。)

SET SERVEROUTPUT ON
DECLARE
CURSOR sal_cursor IS
    SELECT ename, sal
     FROM EMP
FOR UPDATE OF sal NOWAIT;
    V_sal   emp.sal%TYPE;
BEGIN
    FOR emp_record IN sal_cursor
LOOP
    IF (emp_record.sal <= 1000) THEN
        v_sal := emp_record.sal * 1.06;
    ELSIF emp_record.sal > 1000 AND emp_record.sal <= 3000 THEN 
        v_sal := emp_record.sal * 1.08;
    ELSE
        v_sal := emp_record.sal * 1.12;
    END IF;

    UPDATE emp
    SET EMP.sal = v_sal
    WHERE CURRENT OF sal_cursor;

    DBMS_OUTPUT.PUT_LINE(emp_record.ename || ', you just got an n percent raise
    and your new salary is ' || v_sal);
END LOOP;
DBMS_OUTPUT.PUT_LINE('He, he, he... just kidding!');
ROLLBACK;
END;

您还可以使用CASE语句来分配新值;或使用三个单独的UPDATE语句和RETURNING子句来填充v_sal,但不知道您是否已经了解这些语句。

如果要在PL / SQL块中转到ROLLBACK,如果遇到错误,则应该有一个异常处理程序和回滚。