我正在学习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.
提前致谢。
答案 0 :(得分:2)
您的输出表明您尚未启用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语句的测试。来自Explicit Cursor的FETCH不是SQL操作。
SQL%NOTFOUND
永远不会为真,这意味着永远不会满足EXIT WHEN条件。因此,程序在获取所有记录后继续循环。程序抛出ORA-06502
因为emp_data.last
在获取所有记录后为空,因此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;
。虽然这是测试Explicit Cursor是否返回结果的正确语法,但它的行为与批量操作不同(并且不直观)。然后,仅当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()
来表示数字或日期,因此我们可以控制格式。