用PL/SQL创建数据查询过程的时候,存储过程创建并调式都成功,但是调用存储过程查询数据的时候显示“ORA-01422:实际返回行数超过请求行数”。于是我先运行了"select ...... from .....;"语句,这段语句运行成功。存储过程里的查询语句形式为“select ....... into ....... from .....;”。这两种语句中的过滤条件一样,那么为什么第一个语句成功运行,反而第二种语句报错呢?
下面用scott用户自带的emp表为例,跟大家分享我怎么跳出这个坑。
我的目的是通过emp表中的deptno为过滤条件查询emp表中empno,ename,job,sal四个字段,于是我写了第一次的存储过程,代码如下:
create or replace procedure sp_emp1(p_deptno in emp.deptno%type) is v_no emp.empno%type; v_name emp.ename%type; v_job emp.job%type; v_sal emp.sal%type; begin select empno,ename,job,sal into v_no,v_name,v_job,v_sal from emp where deptno=p_deptno; dbms_output.put_line(v_no||‘-----‘||v_name||‘-----‘||v_job||‘------‘||v_sal); end;
上面的存储过程调式成功,然后我调用了sp_emp1存储过程,这时候报错了
--调用sp_emp1 declare v_deptno emp.deptno%type:=&部门号; begin sp_emp1(v_deptno); end;
这里的过滤条件为deptno=30。
于是我运行了
select empno,ename,job,sal from emp where deptno=30;
结果为:
最后比较两个查询语句好像发现了问题在哪儿,select ........ into ..... from ..... ;这段语句中into关键词好像是问题的来源,于是百度一下了这个语句。终于有了答案,本来“select .... int ...... from ....;”语句只能返回单行数据,要是过滤条件后查询出的结果是多行的话,这个语句会报错。
于是,我把存储过程中用游标实现了遍历emp表,使用游标后的存储过程如下:
create or replace procedure sp_emp1(p_deptno in emp.deptno%type) is begin declare cursor cur_emp is select * from emp where deptno = p_deptno; e_cur cur_emp%rowtype; begin dbms_output.put_line(‘工号‘ || ‘-----‘ || ‘姓名‘ || ‘-----‘ || ‘职位‘ ||‘-----‘ || ‘薪资‘); for e_cur in cur_emp loop dbms_output.put_line(e_cur.empno || ‘-----‘ || e_cur.ename ||‘-----‘ || e_cur.job || ‘-----‘ || e_cur.sal); end loop; end; end;
调用修改后的存储过程,查询结果如下:
其实出现“ORA-01422:ORA-01422:实际返回行数超过请求行数”的原因不止这一种,可能还有其他的错误也导致同样的错误代码,以上是我以前遇到的一个情况而已。这个问题说明我们在编写代码的时候要熟悉语句运行的先后循序、返回方式等细节。