插入游标循环和异常处理 - Oracle
我有一个名为 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
真正让我担心的问题是:
如果循环中的插入失败,它应该回滚此事务中所做的所有插入,并且不会以部分插入的记录或孤立的记录结束 交易。我仅在循环完成后提交,没有引发异常。
当发生异常时,我也想知道哪条记录插入失败。我希望在异常中捕获这一点,并在异常处理程序中调用一个函数,将该信息插入到错误表中以供进一步调查。
数据库中禁用自动提交。但是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:
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.
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.
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这种情况下,您也可以使用 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...
基本上,在您描述的情况下,应该不会有问题,因为您仅在回滚后提交。
但也许最好使用 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.