Как выбрать запись, если запросом найдена только одна запись, если больше, вернуть 0 записей?

Как запросом вернуть одну запись, если по условию выборки найдена только одна запись, если больше, то запрос должен вернуть 0 записей?

То есть, для следующего запроса ожидаю:

create table t (val) as
    select 1 from dual union all
    select 1 from dual union all
    select 2 from dual;

select * from t
where val = 1;

no rows selected

Свободный перевод вопроса How to select a record if the query returns one row, or select no record if the query returns more rows от участника @Stalin Gino


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

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

В SQL запросе можно сделать что-то вроде:

select *
from (
    select t.*, count(*) over () total
    from t
    where val = 1
    and rownum <= 2
) where total= 1;

no rows selected

Обратите внимание, что смысл предиката rownum <= 2 заключается в том, чтобы прервать выполнение запроса, если по условию выборки в промежуточном наборе результата будет более 2 записей. То есть, COUNT посчитает максимально две записи, иначе, если по условию выборки будет найдено миллионы строк, то БД сначалa посчитает их все, а затем отбросит, что разумеется крайне неэффективно.

Если запрос в PL/SQL, то при выборке в переменную с INTO var возникнет исключение TOO_MANY_ROWS, если найдено более одной записи:

declare
    var t%rowtype;
begin
    select * into  var
    from t
    where val = 1;
end;

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

→ Ссылка