繁体   English   中英

在过程 pl/sql 中的循环内更新表

[英]Update table inside a loop in a procedure pl/sql

所以我想为一个部门聘请一位新经理。 此过程有 2 个参数,我要更改的部门名称和经理的新 ID(取自员工的 ID)。 因此,要更改它,我需要更新所有拥有旧经理 ID 的员工,并将他们的经理 ID 更改为新经理 ID。 到目前为止,这是我的代码,问题是它更新了所有员工的经理,所以整个数据库都更新了。 我必须使用过程,而不是函数。 任何的想法? 谢谢。

CREATE OR REPLACE PROCEDURE update_manager(v_deptname IN departments.department_name%TYPE,v_empid IN employees.employee_id%TYPE) IS
v_deptid departments.department_id%type;
BEGIN
SELECT department_id INTO v_deptid FROM departments WHERE department_name=v_deptname;
    FOR i IN (SELECT * FROM employees)
    LOOP
        IF i.department_id=v_deptid THEN
            UPDATE employees
            SET manager_id=v_empid
            WHERE i.department_id=v_deptid;
        END IF;
    END LOOP;
END;
/
BEGIN
update_manager('Marketing',100);
END;
/

我没有你的桌子,但我有斯科特的所以 - 这是一个例子。

部门10的部门和员工:

SQL> select * From dept order by deptno;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL> select deptno, empno, ename, mgr
  2  from emp
  3  where deptno = 10;

    DEPTNO      EMPNO ENAME             MGR
---------- ---------- ---------- ----------
        10       7782 CLARK            7839
        10       7839 KING
        10       7934 MILLER           7782

看起来像你的程序(当你正在学习 PL/SQL 时),使用一个变量来获取部门编号,以及一个循环:

SQL> create or replace procedure update_manager
  2    (v_deptname in dept.dname%type,
  3     v_empno    in emp.empno%type
  4    )
  5  is
  6    v_deptno dept.deptno%type;
  7  begin
  8    select d.deptno
  9      into v_deptno
 10      from dept d
 11      where d.dname = v_deptname;      --> this is what you are missing
 12
 13    for cur_r in (select e.empno
 14                  from emp e
 15                  where e.deptno = v_deptno
 16                 )
 17    loop
 18      update emp a set
 19        a.mgr = v_empno
 20        where a.empno = cur_r.empno;
 21    end loop;
 22  end;
 23  /

Procedure created.

测试:让我们修改部门 10 中所有员工的经理:

SQL> exec update_manager ('ACCOUNTING', 7839);

PL/SQL procedure successfully completed.

SQL> select deptno, empno, ename, mgr
  2  from emp
  3  where deptno = 10;

    DEPTNO      EMPNO ENAME             MGR
---------- ---------- ---------- ----------
        10       7782 CLARK            7839
        10       7839 KING             7839
        10       7934 MILLER           7839

SQL>

似乎工作。 但是,这是低效的; 逐行(在循环中)这样做通常是缓慢的。 而是处理整组数据。 像这样的东西:

SQL> rollback;

Rollback complete.

SQL> create or replace procedure update_manager
  2    (v_deptname in dept.dname%type,
  3     v_empno    in emp.empno%type
  4    )
  5  is
  6  begin
  7    update emp e set
  8      e.mgr = v_empno
  9      where e.deptno = (select d.deptno
 10                        from dept d
 11                        where d.dname = v_deptname
 12                       );
 13  end;
 14  /

Procedure created.

SQL> exec update_manager ('ACCOUNTING', 7782);

PL/SQL procedure successfully completed.

SQL> select deptno, empno, ename, mgr
  2  from emp
  3  where deptno = 10;

    DEPTNO      EMPNO ENAME             MGR
---------- ---------- ---------- ----------
        10       7782 CLARK            7782
        10       7839 KING             7782
        10       7934 MILLER           7782

SQL>

如果您必须创建一个 PL/SQL 过程,那么您可以这样做

CREATE OR REPLACE PROCEDURE update_manager(v_deptname IN departments.department_name%TYPE,v_empid IN employees.employee_id%TYPE) IS
  v_deptid departments.department_id%type;
BEGIN
  SELECT department_id INTO v_deptid FROM departments WHERE department_name=v_deptname;
  UPDATE employees
  SET    manager_id=v_empid
  WHERE  department_id=v_deptid;
END;
/

您的代码导致“它更新了所有员工的经理”的问题是您的更新语句:

UPDATE employees
SET manager_id=v_empid
WHERE i.department_id=v_deptid;

您在这里的过滤器正在比较i.department_id ,这是来自您的FOR i IN (SELECT * FROM employees)的变量,而不是来自更新语句的变量。 您已经确认i.department_id=v_deptid因为您正在循环中调用它并使用if语句检查它。

获取员工中的所有行,循环结果,检查每一行是否与条件匹配,然后触发更新语句(即使您的更新语句针对正确的行进行过滤)根本没有效率。

为什么不简单地选择经理 ID 和所有相关员工的更新?

DECLARE @department_id uniqueidentifier

SELECT @department_id = departement_id
FROM departments 
WHERE department_name = @v_deptname

UPDATE employees
SET manager_id = @v_empid
WHERE department_id = @department_id

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM