函数没有为没有返回的行返回值

时间:2019-04-24 00:23:37

标签: oracle plsql

我创建了一个函数,该函数将影片ID作为输入,并根据ID返回股票信息。该功能大部分都有效,但是如果我想从不在数据库中的电影中检索信息(不返回任何行),则不会返回任何内容。不知道为什么吗?

当我调用不返回任何行的ID时不会给我错误,因此异常处理将不起作用。

create or replace function stock_info 
    (p_id IN NUMBER
    )
return VARCHAR2
IS 
    cursor c1 is 
        select movie_id, movie_title, movie_qty
        from mm_movie
        where p_id = movie_id;
    lv_movie_info VARCHAR2(100);
BEGIN

    for i in c1 loop
        if p_id = i.movie_id then 
            lv_movie_info := i.movie_title || ' is available: ' || i.movie_qty || ' on the shelf';
        else
            lv_movie_info := 'no data found';
        end if;
    end loop;

    return lv_movie_info;   
END STOCK_INFO;
/

2 个答案:

答案 0 :(得分:1)

没有数据时您什么也没得到的原因是循环没有执行。逻辑上,For表达式说“为游标中返回的每一行执行以下循环”,但是游标中没有行,因此它永远不会执行该循环。此外,该结构实际​​上表明您期望给定p_id多个。如果不是这种情况,则可以一起消除光标。假设p_id是主键,那么您有0行或1行,因此:

create or replace function stock_info (p_id in number)
return text
is
    lv_movie_info varchar2(100);
begin
    select i.movie_title || ' is available: ' || i.movie_qty || ' on the shelf'
      into lv_movie_info 
      from mm_movie i 
     where p_id = movie_id;

    return lv_movie_info;
exceptions 
   when no_data_found 
   then return 'no data found';
end stock_info; 

当然,如果确实希望多于1行,则需要游标,但是IF不是因为are子句保证它是正确的。仍为0行时,将不会执行循环,因此需要在“结束循环”之后加上“找不到数据”消息。

Belayer

答案 1 :(得分:0)

您使用的游标语句从in参数中获取数据。即在光标中,根据传递的电影ID选择限制。

传递不在数据库中的影片ID时,游标select语句将不会获取任何记录,因此流程甚至都不会进入for循环。

如果您希望不返回任何数据-传递数据库中没有的电影ID时,有两种解决方法  1.在循环之前,使用select语句将标志设置为Y或N(如果存在)并满足您的要求。 2.在不用于光标的情况下,有一个选项可以检查未找到... 样本:

declare
cursor c1 is select * from table_sample; -- empty table
c_rec c1%rowtype;
begin
open c1;
fetch c1 into c_rec;
  if c1%notfound then
      dbms_output.put_line('not found');
   end if;
close c1;
end;

-- output
not found