【问题标题】:Oracle procedure updating all recordsOracle 程序更新所有记录
【发布时间】:2019-01-22 02:08:54
【问题描述】:

您好,我正在尝试使用 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

尽管输出表明它仅针对 emp.id=8 进行更新,但所有记录都在更新。

提前致谢。

【问题讨论】:

  • 不要留下打开的游标,就像在你的函数“ISCOMPGUY”中一样。关闭它。

标签: oracle function stored-procedures oracle11g


【解决方案1】:

我认为您在某种程度上混淆了数据库:

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

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

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

【讨论】:

    【解决方案2】:

    通过将 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;
    

    【讨论】:

    • 你最好把for emp改成另一个名字,因为emp是表,把它命名为另一个例子for ec in ..顺便说一下你在哪里添加提交?
    【解决方案3】:

    我可能刚刚对此发表了评论,但我认为说您使用游标和函数调用这种简单操作的方法绝对无关紧要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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      相关资源
      最近更新 更多