【问题标题】:Error - ORA-06502: PL/SQL: numeric or value error错误 - ORA-06502: PL/SQL: 数字或值错误
【发布时间】:2015-09-01 00:33:17
【问题描述】:

我正在学习 PL/SQL。我使用光标和嵌套表编写了以下过程来显示员工姓名。

create or replace procedure
  employees_data
is
  cursor c1 is select * from employees;
  type empl_tbl is table of c1%rowtype;
  emp_data empl_tbl;
begin
  open c1; 
    LOOP
    fetch c1 bulk collect into emp_data limit 100;
    exit when sql%notfound;
    for i in 1..emp_data.last
      loop
      dbms_output.put_line ('employee name is : ' || to_char(emp_data(i).first_name));
    end loop;
    end loop;
    close c1;
end employees_data;

它编译没有任何错误。当我执行该过程时,我能够显示所有员工的姓名。但是,在显示数据之前会引发以下错误。谁能帮我解决这个问题?

Error starting at line : 1 in command -
exec employees_data()
Error report -
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "HR.EMPLOYEES_DATA", line 12
ORA-06512: at line 1
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

提前致谢。

【问题讨论】:

    标签: oracle plsql bulk-operations


    【解决方案1】:

    您的输出表明您尚未启用 DBMS_OUTPUT。使用set serveroutput on 很明显,一旦处理了所有员工(我在显示中添加了行数),就会引发错误:

    #100:employee name is : Douglas
    #1:employee name is : Jennifer
    #2:employee name is : Michael
    #3:employee name is : Pat
    #4:employee name is : Susan
    #5:employee name is : Hermann
    #6:employee name is : Shelley
    #7:employee name is : William
    BEGIN employees_data; END;
    
    *
    ERROR at line 1:
    ORA-06502: PL/SQL: numeric or value error
    ORA-06512: at "HR.EMPLOYEES_DATA", line 12
    ORA-06512: at line 1
    
    
    SQL> 
    

    那么,为什么会这样呢?这是因为您在 FETCH 之后使用了错误的测试。 SQL%NOTFOUND 是对嵌入在 PL/SQL 中的 SQL 语句的测试。来自显式游标的 FETCH 不是 SQL 操作。

    SQL%NOTFOUND 在 FETCH 之后永远不会为真,这意味着永远不会满足 EXIT WHEN 条件。因此,在获取所有记录后,程序继续循环。程序抛出了ORA-06502,因为在获取所有记录后emp_data.last为null,所以LOOP测试失败了。

    最好的解决方案是测试返回到数组中的行数:

    fetch c1 bulk collect into emp_data limit 100;
    exit when emp_data.count()=0;
    

    通过这一更改,您的程序将运行:

    #100:employee name is : Douglas
    #1:employee name is : Jennifer
    #2:employee name is : Michael
    #3:employee name is : Pat
    #4:employee name is : Susan
    #5:employee name is : Hermann
    #6:employee name is : Shelley
    #7:employee name is : William
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    请注意,您不应使用 exit when c1%notfound; 。尽管这是测试显式游标是否返回结果的正确语法,但其行为与批量操作不同(且不直观)。然后,只有当 FETCH 返回LIMIT 子句中指定的确切行数时,测试才为真。在您的场景中,这意味着您丢失了最后七条记录:

    #98employee name is : Kevin
    #99employee name is : Donald
    #100employee name is : Douglas
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    顺便说一句,强制转换 FIRST_DATE 是不必要的,因为(假设您使用的是标准 HR 模式)它已经是一个字符串。我们需要将to_char() 用于数字或日期等内容,以便我们可以控制格式。

    【讨论】:

    • 您好,先生,非常感谢您的帮助。我使用了 exit emp_data.count=0;没有像以前那样抛出错误。
    • 道歉。由于我是新手,我花了一些时间来理解如何接受它是有帮助的。还有一个问题 - 即使我在 sql%notfound; 时使用了 exit,我也得到了完整的数据 - 107 条记录。请您帮助我理解这一点。
    • 我已经修改了我的问题,以解释为什么对sql%notfound 的测试会导致程序崩溃。我希望你现在能理解为什么会这样。如果您需要进一步说明,请告诉我。
    • 现在我明白了这个错误背后的原因。再一次感谢你。 :)
    猜你喜欢
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2016-12-18
    • 2021-12-26
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多