插入游标循环和异常处理 - Oracle

发布于 2025-01-07 07:55:28 字数 2282 浏览 0 评论 0原文

我有一个名为 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. 数据库中禁用自动提交。但是oracle会将通过循环进行的所有插入视为一个事务或独立事务并立即插入吗?

代码

  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;

I have a table called DUD which is pretty much Static (which means once the data is inserted it never changes). I query data from DUD and populate a staging table CAR from which Webmethods polls everyday.

Usually it is 10 records for every transaction. There are two transactions per day.

I have written a Cursor to do this and I am happy with the logic.

The output will look like:

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

What really concerns me and question is:

  1. If the insert in the loop fails, it should rollback all the inserts made in this transaction and do not end up with partially inserted records or orphaned records for a transaction. I commit only after the loop is completed no exception was raised.

  2. When exception happens, I also want to know which record failed to insert. I hope to catch this in my exception and call a function in the exception handler that will insert this information in to an Error table for further investigation.

  3. The auto commit is disabled in the DB. But will oracle consider ALL the insert through a loop as one transaction or independent transactions and insert it immediately?

Code

  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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骄傲 2025-01-14 07:55:28

在这种情况下,您也可以使用 FORALL 语句...

您正在使用游标,并且在循环中您正在插入表中。
您可以直接一次性插入所有交易。这也会提高代码的性能,并且还可以确保所有事务都插入或没有插入......

You can use FORALL statement also in this situation....

you are using cursor and in loop you are inserting into tables..
you can directly insert all the transactions in one shot. this will increase the performance of your code as well and this will give you surety also that all transaction inserted or none of them have inserted...

夏见 2025-01-14 07:55:28

基本上,在您描述的情况下,应该不会有问题,因为您仅在回滚后提交。
但也许最好使用 AUTONOMOUS_TRANSACTION 作为记录的函数错误。一般来说,应该避免使用它,但由于您需要执行一些原子事务(用于记录记录),因此它可能会更好,因此您将确保此提交不会提交循环中所做的插入。

Basically, in the situation you describe, there shouldn't be a problem, since you commit only after rollback.
But maybe it would be better to use AUTONOMOUS_TRANSACTION for the function that logs the error. In general, one should avoid using it, but since you need to do some atomic transaction (for logging the record) it might be better, so you'll be sure that this commit will not commit the inserts made in the loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文