首页 > 解决方案 > 为什么我有一个错误“精确提取返回的行数超过了请求的行数”?

问题描述

    1. create or replace procedure cities (
    2. vname in varchar2,
    3. vuni out varchar2
    4. ) as
    5. cursor c is
    6. select city_name, uni_name from uni ;
    7. cx c%rowtype;
    8. begin
    9. select uni_name into vuni from uni; 
    10. open c;
    11. loop
    12. fetch c into cx;
    13. exit when c%notfound;
    14. if (vname = 'Almaty') then
    15. select distinct cx.uni_name into vuni from uni where  cx.city_name = vname;
    16. elsif (vname = 'Nur-Sultan') then
    17. select distinct cx.uni_name into vuni from uni where cx.city_name = vname;
    18. elsif (vname = 'Aktau') then
    19. select distinct cx.uni_name into vuni from uni where cx.city_name = vname;
    20. else
    21. select distinct cx.uni_name into vuni from uni where cx.city_name = vname;
    22. end if;
    23. end loop;
    24. close c;
    25. end;

标签: oracleif-statementplsqlcursorprocedure

解决方案


检查SELECT游标外的所有语句。

最可疑的是第 9 行的第一个:

select uni_name into vuni from uni; 

除非UNItable 只包含一行,否则这将返回too_many_rows.

除此之外,还有几种SELECT DISTINCT说法。如果DISTINCT不做它的工作,那么要么你的数据是错误的,要么你的代码是错误的。WHERE也许您需要在子句中添加另一个条件。

无论哪种语句返回错误,最简单的选择是使用聚合函数之一,例如

select max(cx.uni_name) ...

因为它只会返回一个值,但是 - 这很可能是您应该使用的最后一个选项。


[编辑]

等一下; 是的,您遇到了各种错误,但是 - 更仔细地查看您的代码,这没有多大意义。首先,它应该是一个函数,而不是一个过程:

create or replace function f_cities (par_vname in varchar2)
  return uni.uni_name%type
is
  retval uni.uni_name%type;
begin
  select u.uni_name
    into retval
    from u.uni
    where u.city_name = par_vname;

  return retval;
end;

如果它必须是一个程序,那么

create or replace procedure cities
  (par_vname in varchar2,
   par_vuni out varchar2
  )
is
begin
  select u.uni_name
    into par_vuni
    from u.uni
    where u.city_name = par_vname;
end;

从您的代码开始:

  • 您使用的光标不是必需的
  • select陈述是如此奇怪;OUT您正在从同一个表中选择一个游标变量值到参数中,游标select是基于
  • ifs 没用。是in用城市表示的参数;您不必对这些值进行硬编码,因为如果表中有更多引用,该过程可能会成为一个真正的怪物

很快,我建议您使用我在上面发布的功能。


[编辑#2]

根据您的评论:一个城市可以有几所大学。因此,您不能返回标量值,而是返回其他值,例如 ref 游标或数组。

假设这是您拥有的表:

SQL> create table uni
  2    (city_name    varchar2(20),
  3     uni_name     varchar2(20));

Table created.

SQL> insert into uni (city_name, uni_name)
  2    select 'Almaty', 'Uni 1'     from dual union all
  3    select 'Almaty', 'Uni2'      from dual union all
  4    select 'Nur-Sultan', 'Uni 4' from dual union all
  5    select 'Aktau', 'Uni 3'      from dual union all
  6    select 'Aktau', 'Uni 9'      from dual;

5 rows created.

SQL>

现在您可以执行以下操作:

SQL> create or replace function f_uni (par_city_name in varchar2)
  2    return sys.odcivarchar2list
  3  as
  4    rc sys.odcivarchar2list;
  5  begin
  6    select uni_name
  7      bulk collect into rc
  8      from uni
  9      where city_name = par_city_name;
 10    return rc;
 11  end;
 12  /

Function created.

SQL> select f_uni('Almaty') from dual;

F_UNI('ALMATY')
--------------------------------------------------------------------------------
ODCIVARCHAR2LIST('Uni 1', 'Uni2')

或者

SQL> create or replace function f_uni (par_city_name in varchar2)
  2    return sys_refcursor
  3  as
  4    rc sys_refcursor;
  5  begin
  6    open rc for select uni_name
  7          from uni
  8      where city_name = par_city_name;
  9    return rc;
 10  end;
 11  /

Function created.

SQL> select f_uni('Almaty') from dual;

F_UNI('ALMATY')
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

UNI_NAME
--------------------
Uni 1
Uni2


SQL>

推荐阅读