如果包含空值的列,则游标给出NO_DATA_FOUND

时间:2014-04-29 06:21:12

标签: oracle plsql cursor

我将游标定义为

CURSOR all_movie_nominations IS SELECT a.title, a.award_year,n.people_id FROM award a JOIN
                                nominee n ON
                                a.award_id = n.award_id
                                WHERE n.movie_id = (SELECT movie_id FROM movie WHERE movie_name = movieName);

正在打开和关闭光标。

将以下代码中的光标用作

FETCH all_movie_nominations INTO award_title, award_year,nominee_people_id;
WHILE all_movie_nominations%FOUND LOOP

    SELECT given_name, family_name INTO first_name, last_name FROM people WHERE people_id=nominee_people_id;
    IF first_name = '' THEN
    DBMS_OUTPUT.PUT_LINE('The Movie was nominated for '||award_title||' for the year '||award_year);
    ELSE
    DBMS_OUTPUT.PUT_LINE(first_name||' '||last_name||' was nominated for '||award_title||' for the year '||award_year);
    END IF;
    FETCH all_movie_nominations INTO award_title, award_year, nominee_people_id;
END LOOP;

现在游标定义中的属性n.people_id。此列包含某些行的空值。

在执行上面的代码时,我得到了正确的输出,但在输出的末尾有一个'NO_DATA_FOUND`异常。

如果我从光标中排除n.people_id,我就不会有任何异常。

有关可能出错的建议吗?

3 个答案:

答案 0 :(得分:3)

除非这是关于学习使用游标的学生代码,否则在现实生活中永远不会以这种方式编码。循环结构中的SQL语句是一个红色标志。因为你用这种方式锤击数据库,有很多(奖励数量)微小的选择语句检索一个人。这意味着PL / SQL引擎必须多次切换到SQL引擎,导致相对昂贵的上下文切换。如果使用连接,或者在外壳连接中使用,则可以将上下文切换次数最小化为一个。

替代方案的一个例子(当然未经测试):

for r in
( select a.title
       , a.award_year
       , p.given_name
       , p.family_name
    from award
         inner join      nominee n on a.award_id = n.award_id
         left outer join people  p on n.people_id = p.people_id
   where n.movie_id = (select movie_id from movie where movie_name = movieName)
)
loop
  dbms_output.put_line
  ( case 
    when r.given_name is null then
      'The Movie'
    else
      r.given_name || ' ' || r.family_name
    end ||
    ' was nominated for ' || r.title || ' for the year ' || r.award_year
  );
end loop;

答案 1 :(得分:1)

我不确定会发生什么,我认为内部选择句引发了not_found异常:

IF nominee_people_id is not null THEN

   SELECT given_name, family_name INTO first_name, last_name FROM people WHERE       
   people_id=nominee_people_id;

END IF;

我会尝试设置一个条件,检查nominee_people_id是否为空,以便执行这种情况。

我希望它对你有用 Redgards

答案 2 :(得分:0)

Hi you can opt for exception block for that if you want to ignore IF--END IF BLOCK;

BEGIN
SELECT given_name, family_name INTO first_name, last_name FROM people WHERE people_id=nominee_people_id;
EXCEPTION WHEN NO_DATA_FOUND THEN
dbms_output.put_line('no data found for '||nominee_people_id);
END;