如果来自另一个表的数据超过一个值,如何更新表数据



我有三个表:

  • 员工(ssn,工资(
  • WORKS_ON(essn,pid,小时(
  • 项目(pid,pname(

员工的示例数据:

insert into EMPLOYEE values('1011', 1000)
insert into EMPLOYEE values('1012', 1200).

WORKS_ON 的示例数据

insert into WORKS_ON values('1011',80, 60)
insert into WORKS_ON values('1012',90, 40).

项目的示例数据

insert into PROJECT values(80, A)
insert into PROJECT values(90, B).

我需要创建一个存储过程,如果工作时间超过50,则将他/她的工资设置为10%。

这就是我所做的,我在UPDATE方面遇到了问题(也许我的整个代码都错了(,我已经尝试了很多次,但仍然遇到了问题,请帮助我

CREATE OR REPLACE PROCEDURE employee_details(p_ssn IN CHAR) AS
v_ssn employee.ssn%TYPE;
v_sal employee.salary%TYPE;
w_hours works_on.hours%TYPE;
BEGIN
SELECT ssn, salary, hours
INTO v_ssn, v_sal, w_hours
FROM employee NATURAL JOIN works_on
WHERE ssn = p_ssn
AND ssn = essn;
DBMS_OUTPUT.PUT_LINE('Employee_ssn :' || v_ssn);
DBMS_OUTPUT.PUT_LINE('Employee_sal :' || v_sal);
DBMS_OUTPUT.PUT_LINE('Work_hours :' || w_hours);
IF w_hours > 60.0 THEN
v_sal := v_sal + (v_sal * .1);
END IF;
UPDATE employee
SET salary = v_sal
WHERE ssn = essn
AND ssn = p_ssn;
EXCEPTION 
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found.');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Many rows fetched.');
END;

错误:
17/1 PL/SQL:SQL语句被忽略
19/13 PL/SQL:ORA-00904:"ESSN":标识符无效

我的预期结果应该是

Employee_ssn : 1011
Employee_sal : 1100
Work_hours : 60

谢谢!

您有3个结构问题阻碍了代码的运行:

  1. select语句有一个谓词essn=ssn,但是您的表work_hours的描述包含列名emp_ssn。因此,列essn不存在。这是导致错误的直接原因:无效的标识符基本上意味着列不存在
  2. 仍然在选择时,使用谓词employee natural join works_on。这将导致查询永远不会返回行。NATURAL JOIN匹配引用表中具有相同名称的所有列。但是,在引用的表中没有通用的列名
  3. update语句使用谓词ssn=essn。这会导致当前获取的错误,因为列/变量essn不存在

此外,即使将NATURAL JOIN更正为所需的INNER JOIN(或将emp_ssn重命名为essn(,您的示例数据也不会返回任何行,因为您在引用的表中没有匹配的数据值
除了使用dbms_output来显示值(用于调试、我推测的目的或家庭作业的一部分(之外;选择、测试和设置、更新";序列。即使工资没有重新计算,您也会更新行。但整件事都没有必要。它可以通过一个更新语句来完成。如有必要,调用例程
代码和预期结果之间也存在一致性问题。您的代码查找w_hours>60.0,但您的预测结果和样本数据表明w_hours>=60.0。即使你的描述是50。
因此,将程序简化为最低要求。(注意:提供异常消息测试了处理的行数,并引发了要由调用例程处理的适当错误。
最后,过程名称本身没有说明过程的实际操作。这在(IMHO(中是一种非常糟糕的做法。(
所以试试:

create or replace 
procedure increase_salary_for_excessive_hours(p_ssn in employee.ssn%type) as 
begin 
update employee e 
set salary = salary * 1.1
where e.ssn = p_ssn
and exists (select null
from works_hour w
where w.emp_ssn = e.ssn 
and w.hours >= 60
); 

if sql%rowcount < 1 then 
raise no_data_found;
elsif sql%rowcount > 1 then 
raise too_many_rows;
end if;
end increase_salary_for_excessive_hours; 
/

注意:只有当employee.ssn重复时,才会引发异常too_many_rows。如果该列上有适当的唯一(或PK(约束,则永远不会发生。该例程不会为多个符合条件的工作小时增加too_many_rows,而是只更新员工工资一次(但请注意@astentx的警告(

请参阅此处的演示。Demo包含一个生成DBMS_OUTPUT的测试驱动程序。DBMS_OUTPUT适用于测试/调试,但不适用于生产环境
这就引出了最后一点。如果任何一个异常被引发并按当前编写的方式处理,它将编写消息,但调用例程永远不会知道它,并认为一切都成功了。我建议你花一些时间来理解异常部分的实际作用和含义。

您编写的过程使用了不存在的表和列(根据您发布的内容(。

  • works_on应为works_hour
  • 您使用了essn;它是什么
  • 样本数据不匹配;如果SSN=1011,则不能期望它联接到101,因此它不会引发ORA-01422(您使用的标记((too_many_rows(,而是引发no_data_found

我试图修复我认为应该修复的东西。然后编译该过程。

SQL> CREATE OR REPLACE PROCEDURE employee_details(
2    p_ssn IN CHAR
3  )AS
4
5    v_ssn    employee.ssn%TYPE;
6    v_sal    employee.salary%TYPE;
7    w_hours  works_hour.hours%TYPE;  -- works_hour, not works_on
8  BEGIN
9    SELECT ssn,
10           salary,
11           hours
12    INTO
13      v_ssn,
14      v_sal,
15      w_hours
16    FROM employee
17     JOIN works_hour on emp_ssn = ssn
18    WHERE ssn = p_ssn;
19    --AND ssn = v_ssn; -- essn;
20
21    dbms_output.put_line('Employee_ssn :' || v_ssn);
22    dbms_output.put_line('Employee_sal :' || v_sal);
23    dbms_output.put_line('Work_hours :' || w_hours);
24    IF w_hours > 60.0 THEN
25      v_sal := v_sal +(v_sal *.1);
26    END IF;
27
28    UPDATE employee
29    SET
30      salary = v_sal
31    WHERE ssn = v_ssn -- essn
32          AND ssn = p_ssn;
33
34  EXCEPTION
35    WHEN no_data_found THEN
36      dbms_output.put_line('No data found.');
37    WHEN too_many_rows THEN
38      dbms_output.put_line('Many rows fetched.');
39  END;
40  /
Procedure created.
SQL>

它甚至现在工作

SQL> set serveroutput on
SQL>
SQL> exec employee_details('1011');
Employee_ssn :1011
Employee_sal :1000
Work_hours :60
PL/SQL procedure successfully completed.
SQL> select * From employee;
SSN      SALARY
---- ----------
1011       1000
1012       1200
SQL>

我不知道这是否是你想要的。

相关内容

  • 没有找到相关文章

最新更新