在表中找不到给定记录时如何处理游标中的异常

Posted

技术标签:

【中文标题】在表中找不到给定记录时如何处理游标中的异常【英文标题】:How to handle exception in cursor when given record is not found in a table 【发布时间】:2018-03-31 07:20:02 【问题描述】:

我正在使用 Cursor For 循环更新 emp3(与 emp 表相同),

DECLARE 
   CURSOR incr_cur IS SELECT * FROM emp3 FOR UPDATE OF sal;
   v_job emp3.job%TYPE := '&ENTER_Job';
   v_cnt INTEGER := 0;
BEGIN
  FOR r_l IN incr_cur LOOP
    IF v_job IN (r_l.job) THEN
      UPDATE emp3 SET sal = sal + 100 WHERE CURRENT OF incr_cur;
    END IF;
 END LOOP;

 FOR r_l IN incr_cur LOOP
    IF v_job IN (r_l.job) THEN
      v_cnt := v_cnt + 1;
      DBMS_OUTPUT.PUT_LINE('The Salary of ' || r_l.ename || ' is Incremented by 100 and the Updated Salary is: $' || r_l.sal);
    END IF;
 END LOOP;

     DBMS_OUTPUT.PUT_LINE('The Salary of '|| v_cnt ||' Employees are Updated');
END;

当执行 PL/SQL 块时,它会请求作业, 我给MANAGER,那么MANAGER的员工工资加100。 emp3 表有 5 个工作类别 CLERKMANAGERANALYSTSALESMANPRESIDENT。 那么如何显示消息Job未列出,因此无法更新。,如果用户输入了不在表中的JOB,例如DEVELOPER。 我曾尝试过异常处理,但无法正常工作。

【问题讨论】:

有什么理由不使用带有 where 子句的单个 SQL update 语句来完成整个事情? 【参考方案1】:

不需要单独的步骤。只需尝试更新,如果没有更新任何行,就这么说。如果你希望它成为一个例外,那么用raise_application_error 提出一个。

假设这是一个学习练习,这就是为什么你不想只做一个普通的update,你可能会做这样的事情:

declare 
    k_job constant emp3.job%type := '&JOB';

    cursor employees_cur is
        select * from emp3
        where  job = k_job
        for update of sal;

    v_update_count integer := 0;
    v_payroll_increase integer := 0;
begin
    for r in employees_cur loop
        update emp3 set sal = sal + 100 where current of employees_cur;
        dbms_output.put_line('Salary for ' || r.ename || ' is incremented by $100 from $' || r.sal || ' to $' || (r.sal +100));
        v_update_count := v_update_count + 1;
        v_payroll_increase := v_payroll_increase + 100;
    end loop;

    if v_update_count = 0 then
        dbms_output.put_line('No staff are currently employed as ' || k_job ||'. Payroll is unchanged.');
    else
        dbms_output.put_line('Updated salary of '|| v_update_count ||' employee' || case when v_update_count <> 1 then 's' end||'.');
        dbms_output.put_line('Payroll increased by $'||v_payroll_increase||'.');
    end if;
end;
/

Enter value for job: SALESMAN
Salary for ALLEN is incremented by $100 from $1600 to $1700
Salary for WARD is incremented by $100 from $1250 to $1350
Salary for MARTIN is incremented by $100 from $1250 to $1350
Salary for TURNER is incremented by $100 from $1500 to $1600
Updated salary of 4 employees.
Payroll increased by $400.

PL/SQL procedure successfully completed.

对于一个不存在的工作,你会得到这个:

Enter value for job: ASTRONAUT
No staff are currently employed as ASTRONAUT. Payroll is unchanged.

(在此示例中,v_payroll_increase 始终是 v_update_count 的 100 倍,但如果您想加薪 10% 或按部门等进行不同的加薪,这可能更有用。)

【讨论】:

【参考方案2】:

这里有一个选项:检查这样的工作是否存在;如果没有,查询将返回NO_DATA_FOUND,您可以处理它并使用适当的消息引发异常。否则,请继续使用UPDATE

SQL> declare
  2    l_job emp.job%type;
  3  begin
  4    begin
  5      select job
  6        into l_job
  7        from emp
  8        where job = '&ENTER_Job'
  9          and rownum = 1;
 10    exception
 11      when no_data_found then
 12        raise_application_error(-20000, 'That job does not exist');
 13    end;
 14
 15    -- Job exists, so - go on with the update
 16  end;
 17  /
Enter value for enter_job: MANAGER

PL/SQL procedure successfully completed.

SQL> /
Enter value for enter_job: DEVELOPER
declare
*
ERROR at line 1:
ORA-20000: That job does not exist
ORA-06512: at line 12


SQL>

附:忘了提一下:我更喜欢通过存储过程(它接受作业名称作为参数)而不是匿名 PL/SQL 块来完成这样的工作。

【讨论】:

以上是关于在表中找不到给定记录时如何处理游标中的异常的主要内容,如果未能解决你的问题,请参考以下文章

如何处理在源代码中找不到 OpenCV

SQL Server:如果在选择中的函数的表中找不到,则插入记录

使用 Symfony 时如何处理连接表中的附加列?

使用打字稿时如何处理快速控制器方法参数?

Python 的“open()”为“找不到文件”抛出不同的错误——如何处理这两个异常?

将maxInstances用于webdriverio时如何处理登录用户