Какой самый правильный и провереный способ проверки наличия записи в таблице в PL/SQL блоке?

Какой есть правильный и провереный способ проверки наличия записи в таблице, когда использую PL/SQL блок?

Например, есть таблица PERSON (ID, Name). Очевидно, что нельзя сделать (если только нет какого-нибудь секретного метода) что-то в этом роде:

BEGIN 
  IF EXISTS SELECT id FROM person WHERE ID = 10; 
    -- делать что-то если запись найдена
  ELSE
    -- делать что-то если запись еще не сушествует
  END IF;
END;

Так что использую такой стандартный способ решения:

DECLARE
  tmp NUMBER;
BEGIN 
  SELECT id INTO tmp FROM person WHERE id = 10; 
    -- делать что-то если запись найдена
EXCEPTION
  WHEN no_data_found THEN
    -- делать что-то если запись еще не сушествует
END; 

Однако, не уверен, принято ли это так делать, или есть лучший способ проверки.


Свободный перевод вопроса Proper way of checking if row exists in table in pl/sql block от участника @devBem


Ответы (2 шт):

Автор решения: 0xdb

Не стоит помещать код с обычной логикой в блок исключений, там должна быть только обработка исключений.

Сначала проверьте, есть ли записи, и далее реализуйте логику по результатам проверки:

declare
    cursor cur is select 1 from person where id=10; 
    found boolean := false; 
begin 
    open cur; found := cur%found;
    close cur;

    if found then 
        null; -- делать что-то если запись найдена
    else 
        null; -- делать что-то если запись еще не сушествует
    end if;
exception when others then 
    null; -- делать что-то с исключением
end;
/

Или так с неявным курсором:

declare
    found boolean := false; 
begin 
    <<checkIfExists>>
    for r in (select 1 from person where id=10) loop
        found := true;
        exit checkIfExists;
    end loop;
    if found then 
        null; -- делать что-то если запись найдена
    else 
        null; -- делать что-то если запись еще не сушествует
    end if;
exception when others then
    null; -- делать что-то с исключением
end;
/
→ Ссылка
Автор решения: 0xdb

Не стал бы вставлять обычный код в блок исключений.

Просто проверьте, есть ли строки, которые отвечают вашему условию, и продолжайте дальше:

declare
    any_rows_found number;
begin
    select count(*)
    into   any_rows_found
    from   my_table
    where  rownum = 1 and
         ... other conditions ...

    if any_rows_found = 1 then
        ...
    else
        ...
    end if;

Свободный перевод ответа участника @David Aldridge

→ Ссылка