Подтвердить что ты не робот

Как выбрать переменную в PL/SQL, когда результат может быть нулевым?

Есть ли способ просто выполнить запрос один раз, чтобы выбрать в переменную, считая, что запрос ничего не может вернуть, тогда в этом случае переменная должна быть нулевой.

В настоящее время я не могу напрямую использовать переменную select into, так как если запрос ничего не возвращает, PL/SQL будет жаловаться на переменную, которая не будет установлена. Я могу выполнить только запрос дважды, первый - счетчик, и если счетчик равен нулю, установите для переменной значение null, а если число равно 1, выберите в эту переменную.

Итак, код будет выглядеть следующим образом:

v_column my_table.column%TYPE;
v_counter number;
select count(column) into v_counter from my_table where ...;
if (v_counter = 0) then
    v_column := null;
elsif (v_counter = 1) then
    select column into v_column from my_table where ...;
end if;

спасибо.

Обновление: Причина, по которой я не использовал исключение, по-прежнему имеет следующую логику после назначения v_column, и я должен использовать goto в разделе исключения, чтобы перейти к следующему коду. Я немного стесняюсь строк goto.

4b9b3361

Ответ 1

Вы можете просто обработать исключение NO_DATA_FOUND, установив свою переменную в NULL. Таким образом, требуется только один запрос.

    v_column my_table.column%TYPE;

BEGIN

    BEGIN
      select column into v_column from my_table where ...;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        v_column := NULL;
    END;

    ... use v_column here
END;

Ответ 2

Я знаю, что это старый поток, но я все еще думаю, что стоит ответить на него.

select (
        SELECT COLUMN FROM MY_TABLE WHERE ....
        ) into v_column
from dual;

Пример использования:

declare v_column VARCHAR2(100);
begin
  select (SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'DOES NOT EXIST')
  into v_column 
  from dual;
  DBMS_OUTPUT.PUT_LINE('v_column=' || v_column);
end;

Ответ 3

Использование Cursor FOR LOOP Statement - мой любимый способ сделать это.

Это безопаснее, чем использование явного курсора, потому что вам не нужно забывать закрыть его, поэтому вы не можете "просачивать" курсоры. Вам не нужны переменные "в", вам не нужно "FETCH", вам не нужно ловить и обрабатывать исключения "NO DATA FOUND".

Попробуйте, вы никогда не вернетесь.

v_column my_table.column%TYPE;

v_column := null;

FOR rMyTable IN (SELECT COLUMN FROM MY_TABLE WHERE ....) LOOP
  v_column := rMyTable.COLUMN;
  EXIT;  -- Exit the loop if you only want the first result.
END LOOP;

Ответ 4

Я бы рекомендовал использовать курсор. Отбор курсора всегда является одной строкой (если вы не используете массовую коллекцию), а курсоры не автоматически генерируют исключения no_data_found или too_many_rows; хотя вы можете проверить атрибут курсора, когда он открыт, чтобы определить, есть ли у вас строка и сколько.

declare
v_column my_table.column%type;
l_count pls_integer;
cursor my_cursor is
  select count(*) from my_table where ...;

begin
  open my_cursor;
    fetch my_cursor into l_count;
  close my_cursor;

  if l_count = 1 then
    select whse_code into v_column from my_table where ...;
  else
    v_column := null;
  end if;
end;

Или, что еще проще:

    declare
    v_column my_table.column%type;
    cursor my_cursor is
      select column from my_table where ...;

    begin
      open my_cursor;
        fetch my_cursor into v_column;
        -- Optional IF .. THEN based on FOUND or NOTFOUND
        -- Not really needed if v_column is not set
        if my_cursor%notfound then
          v_column := null;
        end if;
      close my_cursor;
    end;

Ответ 5

Как насчет использования MAX? Таким образом, если данные не найдены, переменной присваивается значение NULL, в противном случае - максимальное значение.
Поскольку вы ожидаете значения 0 или 1, MAX должен быть в порядке для использования.

v_column my_table.column%TYPE;
select MAX(column) into v_column from my_table where ...;

Ответ 6

Я использую этот синтаксис для гибкости и скорости -

    begin
    --
    with KLUJ as
    ( select 0 ROES from dual
       union 
      select count(*) from MY_TABLE where rownum = 1
    ) select max(ROES) into has_rows from KLUJ;
    --
    end;

Двойной возвращает 1 строку, rownum добавляет 0 или 1 строки, а max() - ровно 1. Это дает 0 без строк в таблице и 1 для любого другого числа строк.

Я расширяю предложение where, чтобы подсчитывать строки по условию, удалять rownum для подсчета строк, удовлетворяющих условию, и увеличивать rownum для подсчета строк, удовлетворяющих условию до предела.

Ответ 7

Из всех вышеперечисленных ответов ответ Björn кажется самым элегантным и коротким. Я лично использовал этот подход много раз. Функция MAX или MIN выполняет работу одинаково хорошо. Полный PL/SQL следует, только условие where должно быть указано.

declare v_column my_table.column%TYPE;
begin
    select MIN(column) into v_column from my_table where ...;
    DBMS_OUTPUT.PUT_LINE('v_column=' || v_column);
end;

Ответ 8

COALESCE всегда возвращает первый ненулевой результат. Делая это, вы получите нужное количество или 0:

выберите coalesce (count (column), 0) в v_counter из my_table, где...;