当我已经使用游标时,为啥我得到“精确提取返回的行数超过请求的行数”?

Posted

技术标签:

【中文标题】当我已经使用游标时,为啥我得到“精确提取返回的行数超过请求的行数”?【英文标题】:Why did I get the ""exact fetch returns more than requested number of rows" when I use cursor already?当我已经使用游标时,为什么我得到“精确提取返回的行数超过请求的行数”? 【发布时间】:2016-02-14 16:18:27 【问题描述】:

我是用光标写下面的代码,让光标可以拾取多行。但是,它仍然给我错误消息“精确提取返回的行数超过了请求的行数”。游标不是一次检索一行数据吗?为什么仍然显示此消息?

 create or replace trigger e
    before delete on enrollment
    for each row
    declare 
       get_tid scorest.tid%type;
       get_ferm scorest.ferm%type;
       get_sect scorest.sect%type;
       get_name scorest.name%type;
       get_score scorest.score%type;
       cursor findenrolls(atid in scorest.tid%type, 
                          aferm in scorest.ferm%type, 
                          asect in scorest.sect%type)
                          is select * from scorest;
    begin 
       for findenrolls_rec in findenrolls(:old.tid, :old.ferm, :old.sect) loop      
          select tid, ferm, sect, name, score
          into get_tid, get_ferm, get_sect, get_name, get_score
          from scorest
          where scorest.tid=:old.tid
          and scorest.ferm=:old.ferm
          and scorest.sect=:old.sect;

      insert into deleted_scores values (get_tid, get_ferm, get_sect, get_name, get_score);

      delete from scorest
      where tid=get_tid
      and ferm=get_ferm
      and sect=get_sect
      and name=get_name;
   end loop;
end;

【问题讨论】:

【参考方案1】:

您的错误来自此语句部分。 select into 必须返回准确的一条记录。

    select tid, ferm, sect, name, score
      into get_tid, get_ferm, get_sect, get_name, get_score
      from scorest
      where scorest.tid=:old.tid
      and scorest.ferm=:old.ferm
      and scorest.sect=:old.sect;

您必须重写代码才能使其正常工作。在不知道你用例的情况下可能会更难,但你可以试试这个。

CREATE OR REPLACE 
TRIGGER e before DELETE 
ON enrollment 
FOR EACH row 
BEGIN
    FOR get IN (
        SELECT tid
            , ferm
            , sect
            , name
            , score
            FROM scorest
            WHERE scorest.tid=:old.tid
            AND scorest.ferm =:old.ferm
            AND scorest.sect =:old.sect
    )
    LOOP
        INSERT
        INTO deleted_scores VALUES
            ( get.tid
            , get.ferm
            , get.sect
            , get.name
            , get.score
            );

        DELETE
        FROM scorest
        WHERE tid=get.tid
        AND ferm =get.ferm
        AND sect =get.sect
        AND name =get.name;
    END LOOP;
END;

您如何看到显式光标消失并被隐式光标取代,这看起来更适合这种情况。

【讨论】:

【参考方案2】:

由于基于 tid 、 ferm 、 sect 的 scorest 表中的重复数据而出现错误 您可以通过

进行检查
  select  tid , ferm ,sect from scorest having count(1)>1
  group by  tid , ferm ,sect;

如果您不需要重复,则可以在 select 语句中再添加一个条件

 select tid, ferm, sect, name, score
          into get_tid, get_ferm, get_sect, get_name, get_score
          from scorest
          where scorest.tid=:old.tid
          and scorest.ferm=:old.ferm
          and scorest.sect=:old.sect;
          and rownum =1

否则你可以通过“Ftaveras”的建议来接近。

【讨论】:

以上是关于当我已经使用游标时,为啥我得到“精确提取返回的行数超过请求的行数”?的主要内容,如果未能解决你的问题,请参考以下文章

尝试从两列中提取多条记录时,精确提取返回的行数超过了请求的行数

PL/SQL ORA-01422:精确提取返回的行数超过了请求的行数

获取 ORA-01422 的原因:精确提取返回的行数超过了请求的行数

需要 ORA-01422 的解决方案:精确提取返回的行数超过请求的行数

Oracle - ORA-01422:精确提取返回的行数超过了请求的行数

我在编程中不断遇到此问题