简体   繁体   中英

skips a record and uses the previous record data

The question: Write a PL/SQL block that gives raises to each employee according to the following criteria: Save as q3.sql no test script required. • Employees that make less than 1000 get a 6 percent raise • Employees that make between 1000 and 3000 inclusive get an 8 percent raise • Employees that make greater than 3000 get a 12 percent raise With each raise, use dbms_output to print the message ", you just got an n percent raise and your new salary is ". When all raises are completed, rollback the transaction and print the message, "He, he, he...just kidding!"

It does the correct calculations and returns no errors although it's doing the calculations on the previous record and then skipping the next.

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;

The FOR statement already fetches the record from the cursor. So don't execute FETCH in the following line.

You are mixing up two ways of handling cursors - explicit and implicit CURSOR FOR loops. You can compare the examples linked from that syntax page.

The FOR emp_record IN sal_cursor method automatically fetches each row into the emp_record variable. Your explicit FETCH then reads the next record. (I'm slightly surprised it doesn't complain about it).

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;

You could also use a CASE statement to assign the new value; or use the three separate UPDATE statements and the RETURNING clause to populate v_sal , but don't know if you've learned about those yet.

If you are going to ROLLBACK within the PL/SQL block, you should probably have an exception handler and rollback if an error is encountered as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM