Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / IBM DB2, WebSphere, IMS, U2, etc Новый топик    Ответить
 Обработка NO_DATA_FOUND в PL/SQL  [new]
kasyanov
Member

Откуда:
Сообщений: 231
Всем доброго времени суток!
Обнаружил, что неправильно обрабатываю пустой результат select into в своих процедурах.
Набросал тестовый пример, чтобы показать, что именно хочу спросить.


set current schema REPL;
create table TEST (ID INT, NAME VARCHAR(32));
INSERT INTO TEST VALUES (1,'Test');


CREATE OR REPLACE PROCEDURE REPL.SP_TEST (inputid int)
AS
v_name varchar(32);
BEGIN
				select NAME INTO v_name from REPL.TEST where id = inputid;
				if (value(v_name,' ')=' ') then 
					select 'Default' into v_name from dual;				
				end if;
				DBMS_OUTPUT.PUT_LINE(v_name); 
END;
/

set SERVEROUTPUT on
call REPL.SP_TEST(1);
------------------------
Test
DB250000I: Команда выполнена успешно.

call REPL.SP_TEST(2);

SQL0438N Программа генерирует ошибку или предупреждение с текстом диагностики:
"NO_DATA_FOUND".



Подскажите, как правильно переписать код, чтобы обрабатывать такую ситуацию?


Алексей.
1 мар 10, 18:34    [8414231]     Ответить | Цитировать Сообщить модератору
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
kasyanov
Member

Откуда:
Сообщений: 231
Можно отказаться от использования select into в пользу выборки первой записи курсора, но это наворачивает код и делает его менее читабельным. Например,

CREATE OR REPLACE PROCEDURE REPL.SP_TEST (inputid int)
AS
v_name varchar(32);
emp_refcur      SYS_REFCURSOR;
BEGIN
				OPEN emp_refcur FOR 'select NAME from REPL.TEST where id = :inputid' USING inputid;
				FETCH emp_refcur INTO v_name;
				if emp_refcur%NOTFOUND then 
					v_name := 'Default';				
				end if;
				DBMS_OUTPUT.PUT_LINE(v_name); 
				CLOSE emp_refcur;
END;
/

SQL> call REPL.SP_TEST(2);
Default
DB250000I: Команда выполнена успешно.
SQL> call REPL.SP_TEST(1);
Test
DB250000I: Команда выполнена успешно.

Может можно как-то проще?
1 мар 10, 18:55    [8414317]     Ответить | Цитировать Сообщить модератору
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
Mark Barinstein
Member

Откуда: Москва
Сообщений: 4947
CREATE OR REPLACE PROCEDURE TEST_PLSQL (inputid int)
AS
v_name varchar(32);
BEGIN
 begin			
 select NAME INTO v_name from TEST_PLSQL where id = inputid; 
 EXCEPTION
   WHEN NO_DATA_FOUND THEN NULL;
 end;
 if (value(v_name,' ')=' ') then 
  select 'Default' into v_name from dual;				
 end if;
 DBMS_OUTPUT.PUT_LINE(v_name); 
END;
/
2 мар 10, 11:06    [8416676]     Ответить | Цитировать Сообщить модератору
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
Anton Demidov
Member

Откуда: Atlanta, GA
Сообщений: 1187
Подправлю немного
CREATE OR REPLACE PROCEDURE TEST_PLSQL (inputid int)
AS
    v_name VARCHAR(32);
BEGIN
    BEGIN			
        SELECT name INTO v_name FROM test_plsql WHERE id = inputid; 
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
             v_name := 'Default';
    END;
    DBMS_OUTPUT.PUT_LINE(v_name); 
END;
/
12 мар 10, 18:31    [8471229]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
your_frend
Member

Откуда:
Сообщений: 6
Вот пытаюсь в строке сделать изменение, если нет строки с параметром, то создаю c нужными данными:

cursor x is
   select idstr from str where idstr in(значания);
for rx in x loop
   if x%NOTFOUND then
       insert unto str  ..... ;
       RETURNING idstr
      into pidstr;
  else update idstr set ...;
end loop;



вылетает при первом пустом значении ;
Как сделать так чтобы не вылетал из цикла ?
26 авг 20, 20:39    [22187640]     Ответить | Цитировать Сообщить модератору
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
CawaSPb
Member

Откуда: Питер/Москва/Wroclaw
Сообщений: 1091
Используйте MERGE.

Вообще, использовать процедурную логику (итерировать вручную по result set'у) - это крайне порочная практика. Есть исключения (когда, например, надо раздробить слишком большую транзакцию), но лучше оперировать data set'ами непосредственно в SQL.
Это и компактней/более читаемо/проще модифицируемо, и выполнит СУБД это как правило быстрее, и поддерживать проще (особенно в долгосрочной перспективе, когда статистические характеристики данных и, соответственно, оптимальный алгоритм/план доступа к данным могут поменяться, а разработчика уже не найти).

Если же очень надо использовать обработку not found логики, то это делается через CONDITION'ы и HANDLER'ы. Вот как вот здесь.
27 авг 20, 12:02    [22187992]     Ответить | Цитировать Сообщить модератору
 Re: Обработка NO_DATA_FOUND в PL/SQL  [new]
CawaSPb
Member

Откуда: Питер/Москва/Wroclaw
Сообщений: 1091
Вот, кстати, и Том Кайт со мной согласен (:)) (для всех реляционных СУБД это справедливо):
https://asktom.oracle.com/Misc/slow-by-slow.html

На ту же тему:
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1205168148688
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:73891904732164.
27 авг 20, 13:06    [22188045]     Ответить | Цитировать Сообщить модератору
Все форумы / IBM DB2, WebSphere, IMS, U2, etc Ответить