Oracle Cursors : Invalid Identifier

919 views Asked by At

I need to write code that increases the salary of an employee who is over 40 years old.

Here is my code:

DECLARE  
CURSOR kurs IS SELECT  ID_PRACOWNIKA , pensja_BR, wiek FROM PRACOWNICY p , OSOBY o ;
ID_PRACOWNIKA decimal(2):=0;
pensja DECIMAL(8,2);
wiek DECIMAL(2);

BEGIN
    OPEN kurs;
LOOP

   IF wiek > 40 
   THEN
      UPDATE PRACOWNICY 
       SET pensja = PENSJA_BR * 1.02
      WHERE ID_PRACOWNIKA = ID_PRACOWNIKA;

      dbms_OUTPUT.put_line( ID_PRACOWNIKA|| '-'||pensja);
     END IF;
 ID_PRACOWNIKA := ID_PRACOWNIKA+1;
 EXIT WHEN ID_PRACOWNIKA=6;
  END LOOP;
   CLOSE kurs;
   END;

Unfortunately I have SQL error

SQL Error [6550] [65000]: ORA-06550: line 14, column 12:
PL/SQL: ORA-00904: "PENSJA": invalid identifier
ORA-06550: line 13, column 7:
PL/SQL: SQL Statement ignored

Osoby table strucuture:

Id_osoby NUMBER CONSTRAINT osoby_pk PRIMARY KEY,
Imie VARCHAR2(15) NOT NULL,
Nazwisko VARCHAR2(30) NOT NULL,
Wiek NUMBER NOT NULL CONSTRAINT ch_wiek CHECK((Wiek>=0) AND (Wiek<=125)),
Stan_cywilny VARCHAR2(12) NOT NULL,
Telefon VARCHAR2(20),
Pesel CHAR(11) NOT NULL CONSTRAINT osoba_uni UNIQUE,
Id_adresu NUMBER NOT NULL,
CONSTRAINT os_ad_fk FOREIGN KEY (Id_adresu) REFERENCES Adresy(Id_adresu)

Pracownicy table structure:

Id_pracownika NUMBER CONSTRAINT pracownik_pk PRIMARY KEY,
Id_osoby NUMBER NOT NULL CONSTRAINT pr_unique UNIQUE,
Id_stanowiska NUMBER NOT NULL,
Staz NUMBER NOT NULL CONSTRAINT ch_staz CHECK((Staz>=0) AND (Staz<=45)),
Pensja_br NUMBER NOT NULL CONSTRAINT pen_staz CHECK(Pensja_br>=1226),
CONSTRAINT pr_os_fk FOREIGN KEY (Id_osoby) REFERENCES Osoby(Id_osoby),
CONSTRAINT pr_st_fk FOREIGN KEY (Id_stanowiska) REFERENCES Stanowiska(Id_stanowiska)
3

There are 3 answers

1
Popeye On BEST ANSWER

I think you can use the single update statement but as you want to print the details also. You can go with FOR loop as follows:

BEGIN 
FOR I IN (
    SELECT P.ID_PRACOWNIKA,
           P.PENSJA_BR * 1.02 AS PENSJA_BR
      FROM PRACOWNICY   P
      JOIN OSOBY        O
    ON P.ID_OSOBY = O.ID_OSOBY
     WHERE O.WIEK > 40
) LOOP
        UPDATE PRACOWNICY P
           SET P.PENSJA_BR = I.PENSJA_BR
         WHERE P.ID_PRACOWNIKA = I.ID_PRACOWNIKA;

        DBMS_OUTPUT.PUT_LINE(I.ID_PRACOWNIKA || '-' || I.PENSJA_BR);
  END LOOP;
END;

If you just want to update the data with a single query then you can use the following update SQL:

UPDATE PRACOWNICY P
   SET P.PENSJA_BR = P.PENSJA_BR * 1.02
 WHERE EXISTS (
    SELECT 1
      FROM OSOBY O
     WHERE P.ID_OSOBY = O.ID_OSOBY
       AND O.WIEK > 40
);
3
ekochergin On

I believe it's UPDATE clause causing the issue (and the error description say the error is on line 14 of your script)

SET pensja = PENSJA_BR * 1.02

As I see in the beginning, there is a column named pensja_BR in the table PRACOWNICY but you are trying to update the "pensija" column. Which presumably does not exist in the table.

Another things to mention here is there is a cartesian join in your cursor because you're joining two tables without any join/where conditions

UPD: the loop will probably not work here as well because you did not fetched data from. Opening a cursor will not fetch data automatically. You have to either fetch it explicitly every time in the loop

open kurs;
loop
  fetch kurs into some_variable
  ...
end loop;

or to use another for..loop statement in order to loop through the cursor

for k in kurs loop
...
end loop;

So, you need to update cursor definition with following where clause

WHERE p.id_osoby = o.id_osoby and wiek > 40

Then remove the IF > 40 statement, you don't need it anymore. Declare a rowtype variable in DECLARE: kurs_l kurs%rowtype;

in PLSQL: open kurs; loop fetch kurs into kurs_l; exit when kurs%notfound;

  ... do your stuff ...
end loop;
close kurs;
0
Paul C. On

I am not quite sure what the expected result would be but I hava question. If you already have the columns ID_PRACOWNIKA , pensja_BR, wiek retrieved from a table why do you create some variables with the same name?

Now, what I understood from your problem is that you try to change the PENSJA_BR Column to have the value of PENSJA_BR * 1.02 for each row which has the value >40 in the column WIEK.

I think that the following code might help you with your Problem. I have tested it within my testing environment and it updates the column PENSJA_BR accordingly. Nevertheless, you will have to update it to your needs and add what you need extra.

DECLARE

check_stauts NUMBER;

    CURSOR kurs IS 
    SELECT id_pracownika, pensja_br, wiek
    FROM pracownicy;

BEGIN
    FOR i IN kurs LOOP
        if i.wiek > 40 THEN
        UPDATE pracownicy
        SET
            pensja_br = i.pensja_br * 1.02
        WHERE
            id_pracownika = i.id_pracownika; 
    END IF;
    END LOOP;
END;

PS: when trying to assign a value to a variable use:

pensja := PESNJA_BR * 1.02