Вставка в цикл Cursor и обработка исключений - Oracle - PullRequest
1 голос
/ 19 февраля 2012

У меня есть таблица с именем DUD, которая в значительной степени статична (что означает, что после вставки данных она никогда не изменяется).Я запрашиваю данные из DUD и заполняю промежуточную таблицу CAR, из которой Webmethods опрашивает каждый день.

Обычно это 10 записей для каждой транзакции .В день выполняются две транзакции.

Я написал для этого Курсор и доволен логикой.

Вывод будет выглядеть следующим образом:

TRANSID   A    B    C   cnt
------   ---  ---   --  ---
A123     JIM  NY   ACT   1
A123     BOB  CA   ACT   2
A123     PIN  GA   ACT   3
--------------------------
A124     MIK  CA   ACT   1
A124     JON  MA   ACT   2
A124     CON  MY   ACT   3
A124     JIB  CA   ACT   4

Что меня действительно волнует, так и вопрос:

  1. Если вставка в цикле завершается неудачно, она должна откатить все вставки, сделанные в этой транзакции, и не заканчиваться частично вставленными записями или потерянными записямидля транзакция .Я фиксирую только после того, как цикл завершен, исключение не возникло.

  2. Когда происходит исключение, я также хочу знать, какую запись не удалось вставить.Я надеюсь поймать это в моем исключении и вызвать функцию в обработчике исключений, которая вставит эту информацию в таблицу ошибок для дальнейшего исследования.

  3. Автоматическая фиксация отключена в БД,Но будет ли оракул рассматривать ВСЕ вставки через цикл как одну транзакцию или независимые транзакции и вставлять их немедленно?

Код

  DECLARE  TYPE message_info 
  IS 
    RECORD 
    ( 
      message_code INTEGER, 
      message      VARCHAR2(500)); 
    msg MESSAGE_INFO; 
    tranid  NUMBER; 
    p_error EXCEPTION; 
    CURSOR b1 IS 
      SELECT * 
      FROM   dud 
      WHERE  dud.DATE = SYSDATE 
      AND    dud.status='ACTIVE'; 

  BEGIN 
    IF *CHECK SOME condition* 
      BEGIN 
        tranid = seq_transid.NEXTVAL; 
        --- Transaction id is unique per transaction. 
        --- All 10 records will have same transaction id. 
        FOR b1 IN c1 
        LOOP 
          i=b1%rowcount; 
          INSERT INTO car 
                      ( 
                                  transid, 
                                  a, 
                                  b, 
                                  c, 
                                  cnt 
                      ) 
                      VALUES 
                      ( 
                                  tranid, 
                                  b1.a, 
                                  b1.b, 
                                  b1.c, 
                                  i 
                      ); 

        END LOOP; 
      EXCEPTION 
      WHEN OTHERS THEN 
        ROLLBACK; 
        msg.message := 'Unable to insert into CAR Table'; 
        RAISE p_error; 
      END; 
      COMMIT; 
    EXCEPTION 
    WHEN p_error THEN 
      error.post_msg (msg.message, SQLCODE,SQLERRM,USER); 
    END IF; 
  END;

Ответы [ 2 ]

1 голос
/ 19 февраля 2012

Вы можете использовать оператор FORALL и в этой ситуации ....

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

0 голосов
/ 19 февраля 2012

По сути, в описанной вами ситуации не должно быть проблем, поскольку вы фиксируете только после отката.
Но, возможно, было бы лучше использовать AUTONOMOUS_TRANSACTION для функции, которая регистрируетошибка.В целом, следует избегать его использования, но, поскольку вам нужно выполнить некоторую атомарную транзакцию (для записи в запись), она может быть лучше, поэтому вы будете уверены, что этот коммит не будет фиксировать вставки, сделанные в цикле.

...