#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;