如何避免无数据异常?

How to avoid no data exception?

我正在做一个项目,我有一个用 Oracle db 为图书馆编写的数据库模式。我在尝试构建一个应该为用户提供一些建议的功能时遇到了一些问题。

应该根据某个用户在过去一个月里最近借过的图书类型和所有用户阅读次数最多的图书来给出推荐。每次我尝试 运行 该函数时,即使表中有值,我也会收到无数据错误。

    CREATE OR REPLACE FUNCTION getGenre(bookISBN IN VARCHAR2) RETURN VARCHAR2
    AS
      v_bookGenre VARCHAR2(100);
    BEGIN
      select genre into v_bookGenre from (select genre from books where bookISBN=isbn);
      return v_bookGenre;
    END getGenre;
    /
    CREATE OR REPLACE TYPE t IS TABLE OF varchar2(200);
    /
    create or replace type typeRecom is VARRAY(200) of VARCHAR2(200);
    /
    CREATE OR REPLACE FUNCTION topRecommandations(idUser IN VARCHAR2) 
    RETURN typeRecom
    AS

      lastGenres t :=t();
      readedBooks t:=t();
      topTen typeRecom;

      v_i NUMBER := 1;
      v_j NUMBER := 1;

      verifDateBook NUMBER:=0;
      verifDateLoan NUMBER:=0;

    BEGIN
      select count(*) into verifDateBook from books;
      if(verifDateBook = 0) then
        raise no_data_found;
      end if;

      select count(*) into verifDateLoan from loans;
      if(verifDateLoan = 0) then
        raise no_data_found;
      end if;

      lastGenres.extend();
      for i in (select genre from books join loans on books.isbn=loans.bookId where loanDate>add_months(sysdate,-1) and idUser=loans.regNo order by genre desc) loop
        DBMS_OUTPUT.PUT_LINE(i.genre);
        lastGenres.extend();
        lastGenres(lastGenres.count) := i.genre;
      end loop;
      /*select title into bookTitles from book join loan on book.isbn=loan.regNo;*/
       readedBooks.extend();
       for i in (select bookId from loans group by bookId order by count(bookId) desc) loop
        readedBooks.extend();
        readedBooks(readedBooks.count) := i.bookId;
      end loop;
      --select bookId into readedBooks from loan order by count(bookId) desc;

      for v_i IN 1..50 LOOP
        for v_j in 1..50 LOOP
          DBMS_OUTPUT.PUT_LINE(lastGenres(v_j));
          DBMS_OUTPUT.PUT_LINE(getGenre(readedBooks(v_i)));
          if(lastGenres(v_j)=getGenre(readedBooks(v_i))) then
            topTen(v_i) := getGenre(readedBooks(v_j));
          end if;
        EXIT WHEN topTen.count=10;
        END LOOP;
      EXIT WHEN topTen.count=10;
      end LOOP;
      for v_cont in 1..10 LOOP
            --if(topTen.count <= 10) then
            DBMS_OUTPUT.PUT_LINE(topTen(v_cont));
          --end if;
      end loop;
      return topTen;
      EXCEPTION
      WHEN no_data_found THEN 
        DBMS_OUTPUT.PUT_LINE('Nu exista valori.');

    END topRecommandations;

预期结果:包含 10 本推荐书籍的列表。 实际结果:找不到数据错误。

除非我错了,唯一可能 return NO_DATA_FOUND 的地方是 getGenre 函数,因为它有一个 SELECT 一些值到变量中,并且不处理任何异常。其他 SELECTs 使用聚合(如果那里什么都没有,它将 return 0)。

因此,修复该功能,例如

CREATE OR REPLACE FUNCTION getGenre(bookISBN IN VARCHAR2) 
  RETURN VARCHAR2
AS
  v_bookGenre VARCHAR2(100);
BEGIN
  select genre 
    into v_bookGenre
    from books where bookISBN = isbn;

  return v_bookGenre;

EXCEPTION
  when no_data_found then
    return null;
END getGenre;

顺便问一下,为什么要在该函数中使用内联视图?你为什么不直接从 table 本身 return genre(就像我做的那样)?