Oracle Exception Handling - это правильно? - PullRequest
0 голосов
/ 10 ноября 2011

У меня есть следующее ...

IF CONDITION1  THEN

        -- SELECT  STATEMENT MIGHT RETURN DATA

         IF CONDITION2 THEN

                -- SELECT COUNT

             IF CONDITION3 THEN



                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );


            End IF;


    END IF;


 END IF;


EXCEPTION
   WHEN NO_DATA_FOUND THEN
 RETURN;

END of Trigger

Это правильный способ обработки исключений для оператора выбора внутри CONDITION1?

Ответы [ 2 ]

3 голосов
/ 10 ноября 2011

Зависит от того, что вы подразумеваете под «правильным». То, что вы представили, синтаксически верно, да. Но вы не сказали нам, что на самом деле хотите, чтобы мы произошли, поэтому мы не можем сказать, будет ли код, который вы разместили, действительно делать то, что вы хотите.

С точки зрения бизнес-логики, уверены ли вы, что это действительно не ошибка, если ваш SELECT INTO возвращает 0 строк? Если вы ловите и проглатываете исключение, это означает, что вы знаете, что это на самом деле не ошибка. Однако если вы кодируете SELECT INTO, это означает, что вы ожидаете ровно одну строку. Конечно, возможно, что оба эти утверждения верны, но более распространенным является то, что это действительно исключение и что его не следует просто проглотить и игнорировать.

В целом, я бы предпочел поместить обработчик исключений как можно ближе к запросу, который может вызвать исключение, насколько это возможно. Я бы нашел чище иметь что-то вроде

IF condition1
THEN
  BEGIN
    <<select statement>>
  EXCEPTION
    WHEN no_data_found
    THEN
      <<do something>>
  END;

  IF condition2
  THEN
    ...
  END IF;
END IF;

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

Когда вы дойдете до того, чтобы иметь три уровня вложенных операторов IF, я склонен подозревать, что вы хотите реорганизовать код в несколько процедур, чтобы сделать код более понятным. Например, вместо того, чтобы иметь вложенный блок PL / SQL, который выполняет инструкцию SELECT, перехватывает исключение и обрабатывает исключение, вероятно, было бы яснее иметь отдельную функцию, которая выполняла бы все это, а затем вызывать эту функцию из своего триггера.

3 голосов
/ 10 ноября 2011

PL / SQL не может вернуться на сайт с ошибкой, поэтому вам нужно создать блок вокруг той части, которую вы хотите игнорировать:

IF CONDITION1  THEN
         BEGIN
         -- SELECT  STATEMENT MIGHT RETURN DATA
         EXCEPTION
             WHEN NO_DATA_FOUND THEN
                 NULL;
         END;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
    END IF;
 END IF;
END TRIGGER_NAME;

Альтернативой является использование явного курсора, который не возвращает ошибку, когда он пуст:

DECLARE
   CURSOR cur_sample is select dummy from dual where 1=0;
   v_dummy dual.dummy%type;
BEGIN
   IF CONDITION1  THEN
         open cur_sample;
         fetch cur_sample into v_dummy;
         close cur_sample;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
       END IF;
    END IF;
END;
...