Исключение в процедуре - PullRequest
       2

Исключение в процедуре

0 голосов
/ 26 апреля 2018

У меня есть процедура, подобная приведенной ниже, но при запуске блока он не отображает сообщение об ошибке, если данные не найдены.

CREATE OR REPLACE 
PROCEDURE DDPROJ_SP
  (P_IDPROJ IN DD_PROJECT.IDPROJ%TYPE,
   P_INFO OUT VARCHAR2,
   p_check OUT VARCHAR2)
IS
  CURSOR cur_ddproj IS
  SELECT *
  FROM   dd_project
  WHERE  idproj = p_idproj;
  lv_projinfo_txt VARCHAR2(100);
BEGIN
  FOR rec_ddproj IN cur_ddproj LOOP
        lv_projinfo_txt := (rec_ddproj.idproj||', '||rec_ddproj.projname||
                           ', '||rec_ddproj.projstartdate||', '||rec_ddproj.                                 projenddate||
                           ', '||rec_ddproj.projfundgoal||', '||rec_ddproj.p                                rojcoord);
  END LOOP;
  P_INFO := LV_PROJINFO_TXT;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
   P_CHECK :='Please select another project';
   DBMS_OUTPUT.PUT_LINE(P_CHECK);
END;

И блок:

DECLARE
   LV_INFO_TXT VARCHAR2(100);
   LV_CHECK_TXT VARCHAR2(30);
BEGIN
   DDPROJ_SP(00,lv_info_txt,lv_check_txt);
   DBMS_OUTPUT.PUT_LINE(LV_INFO_TXT);
END;

После запускаБЛОК ЕСЛИ указан правильный идентификатор, я получил бы запрошенную информацию, но если идентификатор не найден, исключение не приведет к выводу сообщения на печать.

1 Ответ

0 голосов
/ 26 апреля 2018

Во-первых, как уже указывалось, ваш обработчик исключений не делает ничего действительно видимого, кроме вызова dbms_output, результаты которого вы увидите только в том случае, если вы set serverout on или иным образом получите доступ к результатам из dbms_output.

Во-вторых, и что более важно, когда вы используете цикл FOR для обработки результатов курсора, исключение NO_DATA_FOUND никогда не будет вызвано.

Если вы хотите обнаружить нетНайдены строки, у вас есть несколько вариантов:

  1. После цикла проверьте, установлена ​​ли переменная, например:

    ...
    end loop;
    
    if lv_projinfo_txt is null then
      raise no_data_found;
    end if;
    
  2. Есливы не ожидаете, что по запросу будет найдено более 1 записи (что подсказывается вашим предикатом в «id»), вы можете избежать цикла FOR и использовать простой select into:

    PROCEDURE DDPROJ_SP
      (P_IDPROJ IN DD_PROJECT.IDPROJ%TYPE,
       P_INFO OUT VARCHAR2,
       p_check OUT VARCHAR2)
    IS
    
      rec_ddproj dd_project%rowtype;
    
      lv_projinfo_txt VARCHAR2(100);
    BEGIN
    
      SELECT *
      into   rec_ddproj
      FROM   dd_project
      WHERE  idproj = p_idproj;
    
      lv_projinfo_txt := (rec_ddproj.idproj||',     '||rec_ddproj.projname||
                         ', '||rec_ddproj.projstartdate||', '||rec_ddproj.projenddate||
                         ', '||rec_ddproj.projfundgoal||', '||rec_ddproj.projcoord);
    
      P_INFO := LV_PROJINFO_TXT;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
       P_CHECK :='Please select another project';
       DBMS_OUTPUT.PUT_LINE(P_CHECK);
    END;
    

Примечания:

  • A select into может повысить NO_DATA_FOUND или TOO_MANY_ROWS.

  • Хорошей практикой является никогда не обрабатывать ошибки без повторного вызова исключения, если ваш код фактически не обрабатывает исключение.В вашем случае ваш код просто отправляет сигнал обратно вызывающему процессу через параметр p_check, который перекладывает ответственность за обработку ошибки на вызывающую сторону.Это может быть хорошо в некоторых обстоятельствах, но предполагает, что вызывающий абонент действительно учитывает сигнал.Было бы лучше вызвать исключение, которое заставит вызывающую сторону обработать его соответствующим образом.

  • Хорошей практикой является создание псевдонимов всех столбцов и параметров в запросе;наличие такого предиката SQL, как idproj = p_idproj, предполагает, что в будущем в таблице никогда не будет столбца с именем p_idproj.Вместо этого рекомендуется сознательно создавать псевдонимы для всех столбцов и параметров, например,

    SELECT x.*
    into   rec_ddproj
    FROM   dd_project x
    WHERE  x.idproj = ddproj_sp.p_idproj;
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...