Ваша реализация имеет несколько моментов, которые можно улучшить.
Сначала , если вы ожидаете, что для множества параметров возвращаемый курсор будет пустым,
чем сначала проверьте пустой курсор и только после этой проверки откройте курсор. Вы делаете это наоборот.
Как проверить, пуст ли курсор? К сожалению, вы должны получить первый ряд, чтобы иметь возможность проверить это.
open l_cur for
select id, status from tab where id = p_id;
fetch l_cur into l_id, l_status;
if l_cur%NOTFOUND then
p_Error_Msg := 'Does not Exists';
Return;
end if;
Эта проверка гораздо более эффективна, чем часто используемая count(*)
, поскольку она учитывает только первые (несколько) строк и не учитывает все строки в курсоре.
Если проверка не пройдена, вы готовы, иначе просто откройте курсор и верните его.
open l_cur for
select id, status from tab where id = p_id;
p_Cursor := l_cur;
На ум приходят две дополнительные мысли.
Вам следует изменить общий подход, если база данных очень динамична. Как бы вы справились со случаем, когда другой сеанс удаляет некоторую строку между проверкой и вторым открытием курсора?
Наконец, рассмотрите возможность возврата исключения вместо кода возврата.