PL / SQL проверяет, возвращает ли запрос пустой

#plsql

#plsql

Вопрос:

Я пишу процедуру, и мне нужно проверить, вернул ли мой запрос select пустую запись или нет. (В этом примере отсутствует ли полка x, y)

Как я могу это сделать?

Я пробовал это:

 temp shelves.loadability%TYPE := NULL;
BEGIN

select loadability into temp from shelves where rownumber = x and columnnumber = y;
IF temp IS NOT NULL THEN
/* do something when it's not empty */
ELSE
/* do the other thing when it's empty */
END IF;
  

Но вторая ветвь if никогда не работает…

Редактировать:

О, это было так просто…

 temp shelves.loadability%TYPE;
BEGIN

select count(*) into temp from shelves where rownumber = x and columnnumber = y;
IF temp != 0 THEN
/* do something when it's not empty */
ELSE
/* do the other thing when it's empty */
END IF;

END;
  

Комментарии:

1. выбрать count(*) — не очень хороший способ проверки наличия строк. Смотрите мой ответ ниже для более оптимального подхода

2. Ваша правка должна быть ответом на ваш вопрос.

Ответ №1:

Используйте обработчик исключений

 Begin
  select column
  into variable
  from table
  where ...;

  -- Do something with your variable

exception
 when no_data_found then
    -- Your query returned no rows --

 when too_many_rows
    -- Your query returned more than 1 row --

end;
  

Комментарии:

1. Это хорошая практика? Вы используете exception как condition .

2. Нет, это не очень хорошая практика, смотрите «Совет» в разделе отслеживания ошибок: postgresql.org/docs/current/static /…

3. Это называется обработкой исключений. Так работает plsql.

4. Я не думаю, что это хороший подход. Потому что по определению exceptional condition это случай, с которым программа не знает, как обращаться. В таком случае самое безопасное, что можно сделать, это корректно завершить процесс / функцию / процедуру. Внедрение бизнес-правил внутри graceful shutdown routine не было бы действительно хорошей идеей с точки зрения надлежащей практики программирования!

5. При выполнении выбора … в PLSQL вы должны ожидать 0, 1 или более результатов. И вам нужно обработать эти случаи. Конечно, вы можете сначала выполнить подсчет выборки (*), но нет 100% гарантии, что данные не изменились при выполнении select into мгновением позже. Обработка исключений no_data_found и too_many_rows — это очень стандартный способ работы с запросами select .. into в PLSQL.

Ответ №2:

Обработка исключений тоже была бы первым, о чем я думаю, но если вы не хотите обременять себя обработкой всех разных случаев, я, как правило, использую select count(*) from . Хорошая особенность count (*) в том, что он ВСЕГДА что-то возвращает (при условии, что ваш запрос является законным). В этом случае вы могли бы посчитать, возвращает ли он 0 (нет совпадений) или больше (в этом случае вы можете что-то сделать.

Вы могли бы получить что-то вроде этого:

 declare
  v_count number := 0;
begin
  select count(*) into v_count from table where condition;

  if v_count = 0 then
      --do something
  else
      --do something else
  end if;
end;
  

Ответ №3:

Обычно более похоже на SQL просто выполнять работу для существующих записей. Другими словами, вы могли бы выполнять свою задачу для каждого случая совпадения, и если совпадений нет, вы этого не делаете. Таким образом, вам даже не понадобится конструкция IF-ELSE.

Я не буду рекомендовать использовать курсор для выполнения работы, потому что это противоречило бы моему первому предложению сделать это более похожим на SQL. Но если вам нужно сделать это таким образом, тогда курсор может делать то, что вы хотите.

И да, я понимаю, что это не дает прямого ответа на ваш вопрос.

Комментарии:

1. Но я должен выполнить задачу, если такой полки нет… Я должен вставить кортеж с новой полкой. Извините, если это было непонятно.

2. Итак, есть какие-нибудь советы, как я могу это сделать?

3. @WonderCsabo: Извините, я не вернулся к вопросу вовремя. Рад, что вы разрешили это.

Ответ №4:

поймайте первое нежелательное условие и используйте count(1) поскольку count(*) на самом деле пытается что-то посчитать и добавить rownum = 1, вам нужно только одно первое условие, не соответствующее. я использую этот оператор.

        declare
      v_check number;
    begin
      select count(1) into v_check 
from table
 where condition(something not wanted) AND rownum=1;

      if v_check = 0 then 
           --do something else
      elsif v_check = 1 --dont want theat
         rise some error or more..
      end if;
    end;
  

Для вас просто

 select count(1) into v_check from dual where exists (select count(1) 
    from table
     where condition AND rownum=1);

if v_check = 0 then --nothing found
                 something...
          elsif v_check = 1 --found something
            something...
          end if;
        end;