Oracle 游标:标识符无效
Oracle Cursors : Invalid Identifier
我需要编写代码来增加 40 岁以上员工的工资。
这是我的代码:
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;
不幸的是我有 SQL 错误
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 结构:
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)
自私 table 结构:
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)
我认为是 UPDATE 子句导致了这个问题(错误描述说错误在你脚本的第 14 行)
SET pensja = PENSJA_BR * 1.02
正如我在开头看到的,table PRACOWNICY 中有一个名为 pensja_BR 的列,但您正在尝试更新“pensija”列。 table.
中可能不存在
这里要提到的另一件事是你的光标中有一个笛卡尔连接,因为你要连接两个 table 没有任何 join/where 条件
UPD:循环在这里可能也不起作用,因为您没有从中获取数据。打开游标不会自动获取数据。您必须每次在循环中显式获取它
open kurs;
loop
fetch kurs into some_variable
...
end loop;
或者使用另一个 for..loop 语句来遍历游标
for k in kurs loop
...
end loop;
因此,您需要使用以下 where 子句更新游标定义
WHERE p.id_osoby = o.id_osoby and wiek > 40
然后删除 IF > 40 语句,您不再需要它了。
在 DECLARE 中声明一个 rowtype 变量:
kurs_l kurs%rowtype;
在 PLSQL 中:
打开课程;
环形
将 kurs 提取到 kurs_l;
当 kurs%notfound 时退出;
... do your stuff ...
end loop;
close kurs;
我认为您可以使用单个更新语句,但您还想打印详细信息。您可以按如下方式使用 FOR
循环:
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;
如果您只想通过单个查询更新数据,那么您可以使用以下更新 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
);
我不太确定预期结果是什么,但我有疑问。如果您已经从 table 检索到 ID_PRACOWNIKA 、 pensja_BR 列,为什么要创建一些同名变量?
现在,我从您的问题中了解到,您尝试将 PENSJA_BR 列的值更改为 PENSJA_BR * 1.02,对于列中值 >40 的每一行维克
我认为以下代码可能会帮助您解决问题。我已经在我的测试环境中对其进行了测试,它会相应地更新列 PENSJA_BR。然而,您将不得不根据您的需要更新它并添加您需要的额外内容。
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:尝试为变量赋值时使用:
pensja := PESNJA_BR * 1.02
我需要编写代码来增加 40 岁以上员工的工资。
这是我的代码:
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;
不幸的是我有 SQL 错误
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 结构:
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)
自私 table 结构:
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)
我认为是 UPDATE 子句导致了这个问题(错误描述说错误在你脚本的第 14 行)
SET pensja = PENSJA_BR * 1.02
正如我在开头看到的,table PRACOWNICY 中有一个名为 pensja_BR 的列,但您正在尝试更新“pensija”列。 table.
中可能不存在这里要提到的另一件事是你的光标中有一个笛卡尔连接,因为你要连接两个 table 没有任何 join/where 条件
UPD:循环在这里可能也不起作用,因为您没有从中获取数据。打开游标不会自动获取数据。您必须每次在循环中显式获取它
open kurs;
loop
fetch kurs into some_variable
...
end loop;
或者使用另一个 for..loop 语句来遍历游标
for k in kurs loop
...
end loop;
因此,您需要使用以下 where 子句更新游标定义
WHERE p.id_osoby = o.id_osoby and wiek > 40
然后删除 IF > 40 语句,您不再需要它了。 在 DECLARE 中声明一个 rowtype 变量: kurs_l kurs%rowtype;
在 PLSQL 中: 打开课程; 环形 将 kurs 提取到 kurs_l; 当 kurs%notfound 时退出;
... do your stuff ...
end loop;
close kurs;
我认为您可以使用单个更新语句,但您还想打印详细信息。您可以按如下方式使用 FOR
循环:
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;
如果您只想通过单个查询更新数据,那么您可以使用以下更新 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
);
我不太确定预期结果是什么,但我有疑问。如果您已经从 table 检索到 ID_PRACOWNIKA 、 pensja_BR 列,为什么要创建一些同名变量?
现在,我从您的问题中了解到,您尝试将 PENSJA_BR 列的值更改为 PENSJA_BR * 1.02,对于列中值 >40 的每一行维克
我认为以下代码可能会帮助您解决问题。我已经在我的测试环境中对其进行了测试,它会相应地更新列 PENSJA_BR。然而,您将不得不根据您的需要更新它并添加您需要的额外内容。
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:尝试为变量赋值时使用:
pensja := PESNJA_BR * 1.02