用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:實際返回行數超過請求行數”的原因不止這一種,可能還有其他的錯誤也導致同樣的錯誤代碼,以上是我以前遇到的一個情況而已。這個問題說明我們在編寫代碼的時候要熟悉語句運行的先后循序、返回方式等細節。