您好,我尝试使用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进行更新,所有记录都在更新。
谢谢。
答案 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;