PL/SQL- 使用过程和游标更新薪水
PL/SQL- Updating salary by using Procedure and Cursor
我必须创建一个可以提高员工工资的程序。首先,它要求用户输入 employee_id。如果他的国家是美利坚合众国,职位是 Administration Assistant 或 Stock Manager ,那么加薪 20%。否则回滚。
我在创建过程时遇到问题。我不知道下一步该怎么做。现在有一个错误:
25/5 PL/SQL:语句被忽略
25/112 PLS-00382:表达式类型错误
你能帮帮我吗?
这是我的代码:
CREATE OR REPLACE PROCEDURE raise_emp_salaries (
p_emp_id IN NUMBER) AS
CURSOR c_emp IS
SELECT
countries.country_name,
jobs.job_title,
employees.employee_id,
employees.salary
FROM
countries,
jobs,
employees;
rec_emp c_emp%rowtype;
new_sal NUMBER(12, 2);
BEGIN OPEN c_emp;
SAVEPOINT update_no;
LOOP
FETCH c_emp INTO rec_emp;
EXIT WHEN c_emp%notfound;
IF rec_emp.country_name = 'United States of America' --25/5 PL/SQL: Statement ignored 25/112 PLS-00382: expression is of wrong type
AND rec_emp.job_title = 'Administration Assistant'
OR 'Stock Manager' THEN
new_sal := rec_emp.salary * 1.20;
END IF;
UPDATE employees
SET
employees.salary = new_sal
WHERE
employees.employee_id = p_emp_id;
COMMIT;
end loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO RECORDS');
ROLLBACK TO update_no;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('FOUND SOME KIND OF ERROR');
ROLLBACK TO update_no;
close c_emp;
end;
您的 and/or 不正确。更改为:
IF rec_emp.country_name = 'United States of America'
AND rec_emp.job_title IN ('Administration Assistant','Stock Manager') THEN
IN 基本上是一个 OR 但更容易阅读。
但是你也有逻辑问题。您 SELECT 语句使用了三个表,countries,jobs, employees,并且它们之间没有任何 JOIN。这不可能是正确的,因为这将导致所有三个表中所有行的 CROSS PRODUCT,这可能不是您想要的。由于您没有显示三个表的 DLL,IDK 它们之间的关系,因此您需要弄清楚 JOINS。
此外,通常更好的做法是不要在过程中执行 commit/rollback,并让过程的调用者确定它。如果调用者在会话中执行额外的 DML 怎么办?现在您的程序也具有提交这些更改的 side-effect。您应该 return 过程中的错误 code/message 或创建您自己的异常并引发这些异常。
更多 - 接受 OTHERS 异常而不提供详细信息也是不好的做法。此外,您永远不会遇到 NO_DATA_FOUND 游标实现方式的异常。
已编辑代码。
CREATE OR REPLACE PROCEDURE raise_emp_salaries (
p_emp_id IN NUMBER) AS
CURSOR c_emp IS
SELECT
country_name,
job_title,
employees.employee_id,
salary
FROM employees
JOIN departments on departments.department_id = employees.department_id
JOIN locations on locations.location_id = departments.location_id
JOIN countries ON countries.country_id = locations.country_id
JOIN jobs ON jobs.job_id = employees.job_id;
rec_emp c_emp%rowtype;
new_sal NUMBER(9,2);
BEGIN
OPEN c_emp;
SAVEPOINT update_no;
LOOP
FETCH c_emp INTO rec_emp;
EXIT WHEN c_emp%notfound;
IF rec_emp.country_name = 'United States of America'
AND rec_emp.job_title IN ('Administration Assistant','Stock Manager') THEN
new_sal := rec_emp.salary * 1.20;
END IF;
UPDATE employees
SET
employees.salary = new_sal
WHERE
employees.employee_id = p_emp_id;
COMMIT;
end loop;
close c_emp;
end;`
我必须创建一个可以提高员工工资的程序。首先,它要求用户输入 employee_id。如果他的国家是美利坚合众国,职位是 Administration Assistant 或 Stock Manager ,那么加薪 20%。否则回滚。
我在创建过程时遇到问题。我不知道下一步该怎么做。现在有一个错误: 25/5 PL/SQL:语句被忽略 25/112 PLS-00382:表达式类型错误 你能帮帮我吗?
这是我的代码:
CREATE OR REPLACE PROCEDURE raise_emp_salaries (
p_emp_id IN NUMBER) AS
CURSOR c_emp IS
SELECT
countries.country_name,
jobs.job_title,
employees.employee_id,
employees.salary
FROM
countries,
jobs,
employees;
rec_emp c_emp%rowtype;
new_sal NUMBER(12, 2);
BEGIN OPEN c_emp;
SAVEPOINT update_no;
LOOP
FETCH c_emp INTO rec_emp;
EXIT WHEN c_emp%notfound;
IF rec_emp.country_name = 'United States of America' --25/5 PL/SQL: Statement ignored 25/112 PLS-00382: expression is of wrong type
AND rec_emp.job_title = 'Administration Assistant'
OR 'Stock Manager' THEN
new_sal := rec_emp.salary * 1.20;
END IF;
UPDATE employees
SET
employees.salary = new_sal
WHERE
employees.employee_id = p_emp_id;
COMMIT;
end loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO RECORDS');
ROLLBACK TO update_no;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('FOUND SOME KIND OF ERROR');
ROLLBACK TO update_no;
close c_emp;
end;
您的 and/or 不正确。更改为:
IF rec_emp.country_name = 'United States of America'
AND rec_emp.job_title IN ('Administration Assistant','Stock Manager') THEN
IN 基本上是一个 OR 但更容易阅读。 但是你也有逻辑问题。您 SELECT 语句使用了三个表,countries,jobs, employees,并且它们之间没有任何 JOIN。这不可能是正确的,因为这将导致所有三个表中所有行的 CROSS PRODUCT,这可能不是您想要的。由于您没有显示三个表的 DLL,IDK 它们之间的关系,因此您需要弄清楚 JOINS。
此外,通常更好的做法是不要在过程中执行 commit/rollback,并让过程的调用者确定它。如果调用者在会话中执行额外的 DML 怎么办?现在您的程序也具有提交这些更改的 side-effect。您应该 return 过程中的错误 code/message 或创建您自己的异常并引发这些异常。
更多 - 接受 OTHERS 异常而不提供详细信息也是不好的做法。此外,您永远不会遇到 NO_DATA_FOUND 游标实现方式的异常。
已编辑代码。
CREATE OR REPLACE PROCEDURE raise_emp_salaries (
p_emp_id IN NUMBER) AS
CURSOR c_emp IS
SELECT
country_name,
job_title,
employees.employee_id,
salary
FROM employees
JOIN departments on departments.department_id = employees.department_id
JOIN locations on locations.location_id = departments.location_id
JOIN countries ON countries.country_id = locations.country_id
JOIN jobs ON jobs.job_id = employees.job_id;
rec_emp c_emp%rowtype;
new_sal NUMBER(9,2);
BEGIN
OPEN c_emp;
SAVEPOINT update_no;
LOOP
FETCH c_emp INTO rec_emp;
EXIT WHEN c_emp%notfound;
IF rec_emp.country_name = 'United States of America'
AND rec_emp.job_title IN ('Administration Assistant','Stock Manager') THEN
new_sal := rec_emp.salary * 1.20;
END IF;
UPDATE employees
SET
employees.salary = new_sal
WHERE
employees.employee_id = p_emp_id;
COMMIT;
end loop;
close c_emp;
end;`