簡體   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