【问题标题】:Returned my Cursor in my oracle PL/SLQ function but not all rows are being returned. Can you only return 1 row in a Oracle pl/sql function?在我的 oracle PL/SQL 函数中返回了我的光标,但并非所有行都被返回。您只能在 Oracle pl/sql 函数中返回 1 行吗?
【发布时间】:2020-12-07 04:13:33
【问题描述】:

这是我的代码,我有 2 行共享相同的名称、预订日期和酒店 ID。我不明白为什么当我执行这个函数时,它给了我错误“精确提取返回的行数超过了请求的行数”,而不是在我的保留表中返回我的两行。

我假设我已经正确返回了光标,所以它应该可以工作吗?

CREATE OR REPLACE FUNCTION findres(cname   IN reservation.cust_name%type,
                                   hotelID IN reservation.hotel_id%type,
                                   resdate IN reservation.reserve_date%type)
  RETURN reservation.reserve_id%type is
   resid reservation.reserve_id%type;
BEGIN
    SELECT reserve_id
      INTO resid
      FROM reservation
     WHERE Cust_name = cname
       AND Hotel_id = hotelID
       AND reserve_date = resdate;
    RETURN resid;

  EXCEPTION
    WHEN no_data_found THEN
      dbms_output.put_line('No reservation found'); 
END;
/

【问题讨论】:

  • 您将结果返回到单个变量“resid”中。该变量只能处理 one 值。如果您的查询返回多个值,该函数将抛出错误。

标签: sql oracle plsql


【解决方案1】:

来自into_clause 定义的文档:SELECT INTO 语句从单行中检索一列或多列,并将它们存储在一个或多个标量变量或一个记录变量中

那么当前的 SELECT 语句应该被替换为返回多行的情况。以下查询可能是您当前 SQL Select 语句的替代方法

SELECT reserve_id
  INTO resid
  FROM
  ( SELECT r.*,
           ROW_NUMBER() OVER (ORDER BY 0) AS rn
      FROM reservation
     WHERE Cust_name = cname
       AND Hotel_id = hotelID
       AND reserve_date = resdate
   )
  WHERE rn = 1;

如果数据库版本是 12+,则使用

SELECT reserve_id
  INTO resid
  FROM reservation
 WHERE Cust_name = cname
   AND Hotel_id = hotelID
   AND reserve_date = resdate
 FETCH NEXT 1 ROW ONLY; 

没有子查询以仅返回一行,考虑到您只会获得那些没有数据排序规则的列的重复项。通过使用这些查询,无需处理no_data_foundtoo_many_rows 异常。

更新:如果您的目标是返回所有行,即使一次不止一行,那么您可以使用SYS_REFCURSOR,例如

CREATE OR REPLACE FUNCTION findres(cname   reservation.cust_name%type,
                                   hotelID reservation.hotel_id%type,
                                   resdate reservation.reserve_date%type)
  RETURN SYS_REFCURSOR IS
  recordset SYS_REFCURSOR;
BEGIN
  OPEN recordset FOR
  SELECT reserve_id
    FROM reservation
   WHERE Cust_name = cname
     AND Hotel_id = hotelID 
     AND reserve_date = resdate;

  RETURN recordset;
END;
/

并以这样的方式调用

VAR   v_rc REFCURSOR
EXEC :v_rc := findres('Avoras',111,date'2020-12-06');
PRINT v_rc

来自 SQL Developer 的控制台。

【讨论】:

  • 这似乎不是 OP 想要的。如果 SELECT 语句返回两行,他确实想要返回这两行。可以这样做,但不是按照您建议的方式。
  • 是的,我喜欢返回两行而不是其中一行
  • 好吧,但是他说你只能在 Oracle pl/sql 函数中返回 1 行吗? @mathguy
  • 是的 - 这个问题,用正确的英语(正如 OP 使用的那样),可以改写为:“在 Oracle PL/SQL 中,一个函数是否只能返回一行?”我相信你认为这意味着不同的东西。
  • 好的,由于您上次的评论@Avoras 更新了答案
猜你喜欢
  • 2021-04-28
  • 2013-11-20
  • 2012-10-31
  • 1970-01-01
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
相关资源
最近更新 更多