简体   繁体   中英

How do I resolve this procedure in PL/SQL

I'm stanqued in sequence of PL/SQL procedure I need to do a procedure that receives as parameters a department number, a salary, and a percentage; and to raise the salary of all employees of the department indicated in the call. The increase will be the percentage or salary indicated in the call (whichever is more beneficial for the employee in each case). I have this code but doesn't work.

CREATE OR REPLACE PROCEDURE pujarSalari (numdept number,diners number,percentatge number)
AS
souapujar number(10);
CURSOR buscarnoms IS SELECT codi_emp FROM empleats WHERE codi_dept=numdept;
BEGIN
OPEN buscarnoms;
FETCH buscarnoms INTO souapujar;
WHILE buscarnoms%FOUND LOOP
IF (empleats.sou*(1+percentatge/100))>=(empleats.sou+diners) THEN
UPDATE empleats set empleats.sou=empleats.sou*(1+percentatge/100) where codi_emp=souapujar;
ELSE
UPDATE empleats set empleats.sou=empleats.sou+diners where codi_emp=souapujar;
END IF;
FETCH buscarnoms INTO souapujar;
END LOOP;
CLOSE buscarnoms;
END; 

And the error code is

Procedure PUJARSALARI compilado

LINE/COL  ERROR
--------- -------------------------------------------------------------
9/1       PL/SQL: Statement ignored
9/14      PLS-00357: Table,View Or Sequence reference 'EMPLEATS.SOU' not allowed in this context
Errores: comprobar log de compilador

Your IF statements are referencing table columns . In PL/SQL we can only reference variables (including implicit cursors). (That is outside of embedded SQL statements.)

You have a cursor buscarnoms which selects from empleats but doesn't include all the columns you need. So you must change the cursor projection then reference the cursor in your code.

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
  CURSOR buscarnoms IS 
    SELECT * 
    FROM empleats 
    WHERE codi_dept = numdept;
  souapujar buscarnoms%rowtype; -- inherits the projection of the cursor
BEGIN
  OPEN buscarnoms;
  FETCH buscarnoms INTO souapujar;
  WHILE buscarnoms%FOUND LOOP
    IF (souapujar.sou*(1+percentatge/100)) >= (souapujar.sou+diners) THEN
        UPDATE empleats 
        set empleats.sou = empleats.sou*(1+percentatge/100) 
        where codi_emp = souapujar.codi_emp;
    ELSE
      UPDATE empleats 
      set empleats.sou = empleats.sou+diners 
      where codi_emp = souapujar.codi_emp;
    END IF;
    FETCH buscarnoms INTO souapujar;
  END LOOP;
  CLOSE buscarnoms;
END; 

There are several ways to simplify this code, for instance by replacing the explicit cursor with an implicit cursor. Or even replacing the cursor loop with a set-based update statement. But I have left the code as close to the original as possible, to highlight the solution to the problem as presented.


You say that are several ways to simplify the code. How can i simplify my code?

Implicit cursor:

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
BEGIN
  FOR buscarnoms in (SELECT * 
                     FROM empleats 
                     WHERE codi_dept = numdept)
  LOOP
    IF (souapujar.sou*(1+percentatge/100)) >= (souapujar.sou+diners) THEN
        UPDATE empleats 
        set empleats.sou = empleats.sou*(1+percentatge/100) 
        where codi_emp = souapujar.codi_emp;
    ELSE
      UPDATE empleats 
      set empleats.sou = empleats.sou+diners 
      where codi_emp = souapujar.codi_emp;
    END IF;
  END LOOP;
END; 

Set-based:

CREATE OR REPLACE PROCEDURE pujarSalari 
  (numdept number,
   diners number,
   percentatge number)
AS
BEGIN

  UPDATE empleats 
  set    sou = greatest(empleats.sou + diners, 
                        empleats.sou * (1+percentatge/100) )
  where codi_dept = numdept;

END; 

Well that actually is a different question and should be posed that way. But how about max simplification. Reduce it to a single statement:

 create or replace procedure pujarsalari 
      (numdept     number,
       diners      number,
       percentatge number)
    as
    begin
        update empleats 
           set sou = greatest(sou*(1+percentatge/100), sou+diners)   
         where codi_dept = numdept;
    end  pujarsalari;

Tip of the day: In SQL stop thinking in terms of individual rows. Think instead of the set of all rows at one time.

NOTE: Not tested as you did not see fit to post neither sample data not table definitions.

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