PL/SQL 中未更新的行
Posted
技术标签:
【中文标题】PL/SQL 中未更新的行【英文标题】:Rows not updated in PL/SQL 【发布时间】:2020-05-16 19:32:30 【问题描述】:我想将给定部门中用户的工资更新 10K,如果他们的名称中有 T,否则为 n*10k,其中 n 是从 1 到 5 的 saraly 类别。但不知何故,更新查询不会更新行。
我创建了一个游标,并将它们提取到 rec 变量中。然后检查名称是否有 'T',否则我将 inc 变量设置为薪金类别并适当地更新该行。
CREATE OR REPLACE PROCEDURE sal_increase(p_deptno INTEGER) IS
cursor curs is select empno, e.ename, e.sal, sc.category , lowest_sal, highest_sal
from emp2 e
join nikovits.sal_cat sc on lowest_sal <= sal and sal <= highest_sal
where deptno = p_deptno FOR UPDATE;
rec curs%ROWTYPE;
i integer := 1;
i_out varchar2(30);
inc integer := 1;
has_t integer := 0;
begin
OPEN curs;
loop
FETCH curs INTO rec;
EXIT WHEN curs%NOTFOUND;
has_t := 0;
for i in 1..length(rec.ename) loop
i_out := substr(rec.ename,i,1);
if i_out = 'T' then
has_t := 1;
end if;
end loop;
if has_t = 0 then
inc := rec.category;
end if;
if has_t = 1 then
DBMS_OUTPUT.PUT_LINE(rec.ename||' has T, increment is 10000');
else
DBMS_OUTPUT.PUT_LINE(rec.ename||' Doesnt have T, salery category is '|| rec.category ||' increment is '|| inc ||'*10000');
end if;
DBMS_OUTPUT.PUT_LINE('update begins...');
UPDATE emp2 e1 SET sal = sal + (inc * 10000) WHERE CURRENT OF curs;
DBMS_OUTPUT.PUT_LINE('After update'||rec.ename||'"salary: '||rec.sal);
end loop;
CLOSE curs;
end;
/
set serveroutput on
execute sal_increase(20);
select empno, e.ename, e.sal, sc.category , lowest_sal, highest_sal
from emp2 e
join nikovits.sal_cat sc on lowest_sal <= sal and sal <= highest_sal where deptno = 20;
【问题讨论】:
İ如果你不介意,你能分享创建脚本表emp2和sal_cat吗? 我没有,但添加了图片 你必须检查名称是否包含'T'的整个for循环可以替换为INSTR call 希望 ROLLBACK 被故意留在你的脚本中,你知道它为什么在那里,对吧? @micklesh 是的,我不想破坏表格的内容。反正我没有运行它 【参考方案1】:您不需要 PL/SQL 块。仅使用单个 Update 语句就足够了:
UPDATE emp2 e1
SET sal = sal +
(
SELECT 10000 * case when instr(e.ename,'T')>0 then 1 else sc.category end
FROM emp2 e
JOIN sal_cat sc
ON lowest_sal <= sal
AND sal <= highest_sal
WHERE empno = e1.empno
)
WHERE deptno = :p_deptno;
如果员工的姓名包含字母T
,则其工资系数等于1
【讨论】:
我知道。我不得不用 PL/SQL 来做。这就是任务。但你是对的。我也发布了使用 PL/SQL 的工作解决方案 只需将此语句放入您的程序中。无需使用带有混乱 @FəridQənbərli 的光标。顺便说一句,不要忘记删除参数 p_deptno 之前的冒号。 哇。结果是更好的解决方案!【参考方案2】:事实证明,在 PL/SQL 中使用游标更新表不起作用,因为游标看不到新值,所以正确的 anwser 应该是
CREATE OR REPLACE PROCEDURE sal_increase(p_deptno INTEGER) IS
i integer := 1;
i_out varchar2(30);
inc integer := 1;
has_t integer := 0;
begin
for rec in (
select empno, e.ename, e.sal, sc.category , lowest_sal, highest_sal
from emp2 e
join nikovits.sal_cat sc on lowest_sal <= sal and sal <= highest_sal
where deptno = p_deptno
) loop
has_t := 0;
for i in 1..length(rec.ename) loop
i_out := substr(rec.ename,i,1);
if i_out = 'T' then
has_t := 1;
end if;
end loop;
if has_t = 0 then
inc := rec.category;
end if;
if has_t = 1 then
DBMS_OUTPUT.PUT_LINE(rec.ename||' has T, increment is 10000');
else
DBMS_OUTPUT.PUT_LINE(rec.ename||' Doesnt have T, salery category is '|| rec.category ||' increment is '|| inc ||'*10000');
end if;
DBMS_OUTPUT.PUT_LINE('update begins...');
UPDATE emp2 e1 SET sal = sal + (inc * 10000)
where e1.empno = rec.empno and e1.deptno = p_deptno;
DBMS_OUTPUT.PUT_LINE('After update'||rec.ename||'"salary: '||rec.sal);
rollback;
end loop;
end;
/
set serveroutput on
execute sal_increase(20);
select empno, e.ename, e.sal
from emp2 e where deptno = 20;
rollback;
【讨论】:
以上是关于PL/SQL 中未更新的行的主要内容,如果未能解决你的问题,请参考以下文章
如何提取 Count(*) 中的行数,并发送到变量。 (PL/SQL)
PL/SQL连接Oracle,提示ORA-12504:TNS监听程序在connect-data中未获得service-name
PL/SQL ORA-01422:精确提取返回的行数超过了请求的行数