Я работаю над проектом, и у меня есть схема базы данных, написанная в 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 рекомендуемых книг. Фактический результат: ошибка данных не найдена.
Если я не ошибаюсь, единственное место, которое может вернуть NO_DATA_FOUND
, — это getGenre
функция, поскольку она имеет SELECT
какое-то значение в переменной, и никакие исключения не обрабатываются. Другие SELECT
используют агрегаты (которые возвращают 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;
Кстати, почему вы использовали встроенное представление в этой функции? Почему ты просто не вернулся genre
из-за стола (как я)?
Спасибо, вы правы! Я хотел что-то еще из представления, и я забыл его удалить.
Проверьте свои операторы if.. Они явно говорят.. no_data_found