Oracle过程更新所有记录

时间:2018-08-15 07:33:03

标签: oracle function stored-procedures oracle11g

您好,我尝试使用Oracle中的存储过程从表中更新特定记录, 但会更新所有记录而不是特定记录。 这是我执行存储过程之前的EMP表

ID, NAME, DEPT, SAL
1   pc    New   100000000
2   pc1   qwe   1
3   pc2   New   2
4   pc4   asf   3
5   pc5   New   4
6   pc6   qwe   5
7   pc7   New   6
8   pc8   COMP  8
9   pc9   New   9
10  pc10  New   7
11  pc11  qwe   11
12  pc12  New   12
13  pc13  New   13
14  pc14  qwe   14

检查是否为EMP的功能属于COMP部门

create or replace FUNCTION ISCOMPGUY 
(
  EMPID IN NUMBER 
) RETURN NUMBER AS

dept varchar(20);

cursor getDept IS select dept from emp where id=EMPID;

BEGIN
    open getDept; FETCH getDept INTO dept;
    IF DEPT = 'COMP' THEN 
        return 1;
    ELSE
        return 0;
    END IF;
END ISCOMPGUY;

根据ISCOMPGUY函数更新记录的过程

CREATE OR REPLACE PROCEDURE UPATEEMP AS 

isValid number :=0;

cursor getCompGuys IS select id from emp;-- where dept='COMP';
BEGIN
    for emp in getCompGuys loop
        isValid := iscompguy(emp.id);
        dbms_output.put_line ('isValid '|| emp.id || ' : ' || isValid );
        if isValid = 1 then
            dbms_output.put_line ('updating ' ||emp.id);
                UPDATE EMP set dept='IT' where id = emp.id;
        end if;        
     end loop;
END UPATEEMP;

但是当我运行过程时,它会更新所有记录 执行过程后输出过程和EMP表

Connecting to the database testDB.
isValid 1 : 0
isValid 2 : 0
isValid 3 : 0
isValid 4 : 0
isValid 5 : 0
isValid 6 : 0
isValid 7 : 0
isValid 8 : 1
updating 8
isValid 9 : 0
isValid 10 : 0
isValid 11 : 0
isValid 12 : 0
isValid 13 : 0
isValid 14 : 0
Process exited.
Disconnecting from the database testDB.

ID, NAME, DEPT, SAL
1   pc      IT  100000000
2   pc1     IT  1
3   pc2     IT  2
4   pc4     IT  3
5   pc5     IT  4
6   pc6     IT  5
7   pc7     IT  6
8   pc8     IT  8
9   pc9     IT  9
10  pc10    IT  7
11  pc11    IT  11
12  pc12    IT  12
13  pc13    IT  13
14  pc14    IT  14

Eventhough输出显示仅针对emp.id = 8进行更新,所有记录都在更新。

谢谢。

3 个答案:

答案 0 :(得分:2)

我可能刚刚对此发表了评论,但是我认为说这样简单的操作使用游标和函数调用的方法是绝对非必要 sub -最佳解决方案。

看来您真正想要的是这样的更新语句。

UPDATE emp
    SET
        dept = 'IT'
    WHERE dept = 'COMP';

这比通过游标遍历所有值并编写不必要的代码要有效和高效。

如果您只想显示更新了哪些ID,那么您可能要做的就是使用RETURNING BULK COLLECT INTO语句来存储和从集合中获取ID。

CREATE OR REPLACE PROCEDURE upateemp AS
    TYPE empidtyp IS
        TABLE OF emp.id%TYPE;
    empids   empidtyp;
BEGIN
    UPDATE emp
    SET
        dept = 'IT'
    WHERE dept = 'COMP' RETURNING id BULK COLLECT INTO empids; --store the updated ids in a collection

    FOR i IN 1..empids.count LOOP --loop through collection elements
        dbms_output.put_line('isValid ' || empids(i) ); 
    END LOOP;

END upateemp;
/

执行

SET SERVEROUTPUT ON
BEGIN
 EXEC upateemp;
END;
/
isValid 8


PL/SQL procedure successfully completed.

答案 1 :(得分:1)

我认为您对此感到有些困惑:

UPDATE EMP set dept='IT' where id = emp.id;

那么emp.id等于什么?系统是否认为这是for循环中的emp,还是对语句本身中对EMP表的引用。我怀疑它会在解析它时首先放置更本地的emp表引用,在这种情况下,更新将要求更新id = id的地方,例如所有行。

我将更改循环变量上的别名作为重新测试

答案 2 :(得分:0)

通过将emp.id放入新变量并将其传递给更新命令来解决

CREATE OR REPLACE PROCEDURE UPATEEMP AS 

isValid number :=0;
eid number;

cursor getCompGuys IS select id from emp;-- where dept='COMP';
BEGIN
    for emp in getCompGuys loop
        isValid := iscompguy(emp.id);
        eid := emp.id;
        dbms_output.put_line ('isValid '|| emp.id || ' : ' || isValid );
        if isValid = 1 then
            dbms_output.put_line ('updating ' ||emp.id);
            UPDATE EMP set dept='IT' where id = eid;
        end if;        
     end loop;
END UPATEEMP;