为啥我得到的准确提取返回超过请求的行数

Posted

技术标签:

【中文标题】为啥我得到的准确提取返回超过请求的行数【英文标题】:why am I getting exact fetch returns more than requested number of rows为什么我得到的准确提取返回超过请求的行数 【发布时间】:2015-12-11 20:17:02 【问题描述】:

这是获得对某项最高出价的userID 的过程。如果在maxPrice 上出现平局,那么获胜者将成为最先出价的人,给出该项目的itemIDcurrentPrice(中标)。

create or replace FUNCTION GARAGESALE_getWinner(id1 int, currentPrice int) Return varchar2 RESULT_CACHE
AS
  uname varchar2(30) := 'none';
Begin
  SELECT C1.username into uname
  FROM GARAGESALE_BID B, GARAGESALE_Customer C1
  WHERE B.maxPrice >= currentPrice 
    and C1.userID = B.UserID 
    and B.itemID = id1 
    and not exists (select * 
                    from GARAGESALE_BID B2
                    where B2.bdate < B.bdate 
                      and B.maxprice = B2.maxprice 
                      and B2.itemID = B.itemID); 
  return uname;

End;

这是错误信息:

连接到数据库 Team 3. ORA-01422: 精确提取返回的行数多于请求的行数 ORA-06512:在“TEAM3.GARAGESALE_GETWINNER”,第 7 行 ORA-06512:在第 9 行 进程已退出。 与数据库 Team 3 断开连接。

【问题讨论】:

对于给定的UserID 值,您是否可能在GARAGESALE_Customer 中有多个记录? 只需运行不带 SQL*Plus(或 TOAD 或其他)中的 INTO 子句的查询,无论 id1currentPrice 的值都失败,看看多行是什么。 刚试了一下,它返回了我希望它返回的一行。 【参考方案1】:

摆脱相关的子查询将减少您需要的表扫描次数:

CREATE FUNCTION GARAGESALE_getWinner(
  i_itemID        IN  GARAGESALE_BID.ITEMID%TYPE,
  i_currentPrice  IN  GARAGESALE_BID.MAXPRICE%TYPE
) RETURN GARAGESALE_CUSTOMER.USERNAME%TYPE RESULT_CACHE
AS
  uname GARAGESALE_CUSTOMER.USERNAME%TYPE;
BEGIN
  SELECT  username
  INTO    uname
  FROM    (
    SELECT  C.username
    FROM    GARAGESALE_BID b
            INNER JOIN GARAGESALE_CUSTOMER c
            ON ( b.userID = c.userID )
    WHERE   b.maxPrice >= i_currentPrice
    AND     b.itemID   =  i_itemID
    ORDER BY
            b.maxPrice DESC,
            b.BDATE    DESC,
            b.userID   ASC
  )
  WHERE   ROWNUM = 1;

  RETURN uname;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RETURN 'none'; -- Really? Why not NULL?
END GARAGESALE_getWinner;
/
SHOW ERRORS;

不清楚如果两个用户同时提交了相同的maxPrice,那么抢七是什么 - 我选择了最早的userID作为非随机的打破平局的方法。

【讨论】:

【参考方案2】:

此错误表示您选择返回多于 1 行。

要使用“into”关键字,您必须确保只获得 1 行结果。

可以通过将'rownum'添加到约束来完成。

SELECT C1.username into uname
  from GARAGESALE_BID B, GARAGESALE_Customer C1
  WHERE rownum < 2 and 
       B.maxPrice >= currentPrice and C1.userID = B.UserID and B.itemID = id1 and  not exists (select * 
                                                From GARAGESALE_BID B2
                                                where B2.bdate < B.bdate and B.maxprice = B2.maxprice and B2.itemID = B.itemID)

这将确保您的选择仅返回 1 行。

如果您需要超过 1 行来返回,请尝试使用循环或游标。

【讨论】:

投反对票,因为那是创可贴。如果您希望获得 1 行并获得 2 行,则意味着您有错误。随机选择其中一个只是为了让您的代码“工作”不是答案。 @MatthewMcPeak 我们不知道确切的要求,也许选择随机行是可以的。无论如何我的答案 - 取决于。

以上是关于为啥我得到的准确提取返回超过请求的行数的主要内容,如果未能解决你的问题,请参考以下文章

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

“精确提取返回的行数超过了请求的行数”

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

“确切的提取返回超过请求的行数”

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

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