PL/SQL 中的异常处理和回滚

Posted

技术标签:

【中文标题】PL/SQL 中的异常处理和回滚【英文标题】:Exception handling and rollbacks in PL/SQL 【发布时间】:2018-07-04 13:17:27 【问题描述】:

目前,我有一个带有 PLAN_A 的表 FIRST_ENTRY_TABLE,其他 11 个表具有相对于 PLAN_A 的相应 customer_ID。我有一个带有新键的临时表,它将替换 PLAN_A 并为相应的 customer_is 添加 PLAN_B。 下面是 12 个 PL/SQL 过程,它将新的 PLAN_B 插入/更新到与 customer_id 相关的所有必需表中。 因为大约有 100 000 个 PLANS 将被 customer_ids 的 NEW PLAN KEY 取代。

首先,我正在创建游标并读取要在 12 个表中更新的所有新 KEY。

然后通过12个Procedure分别在12个表中插入/更新查询。

DECLARE
var1
CURSOR C1
select query fetching PLAN_B key from temp table
PROCEDURE procedure1(
P_key IN OFFTABLE%TYPE;
IS
BEGIN
INSERT into FIRST_ENTRY_TABLE( 
mandator_key,OFFER_TYPE_KEY,offer_key)VALUES('abc','FIXED',P_key)
RETURNING ID
INTO var1;
 END procedure1;
 )
PROCEDIRE procedure2(
 P_key IN OFFTABLE%TYPE;
 oldid IN FIRST_ENTRY_TABLE%TYPE;
 )
IS
 BEGIN
 INSERT into SECOND_ENTRY_TABLE(col1,col2...custid)
 select (col1,col2...var1) FROM sometable WHERE offer_key= P_key;
 UPDATE SECOND_ENTRY_TABLE set custid=var1 where custid=oldid;
 END procedure2;

 simplarly procedure3

 procedure4..  procedure5

 --------procedure12
 COMMIT;

我的问题是如何在这里进行异常处理,因为我有所有插入和更新语句。 我知道使用 NO_DATA_FOUND,所有其他异常都可能出现,我们如何在这里处理它。 异常如何处理,到底是在所有程序执行后COMMIT还是在每个程序内部?

如何从所有 12 个表中进行回滚?将有新插入键的删除脚本和更新查询的计划在几个表中得到更新。但会有超过 10 万条记录。有什么办法可以写程序在程序执行前进行回滚?

【问题讨论】:

我不明白。你想做什么? @BobJarvis 我正在尝试使用动态 SQL。简而言之,我总共有 12 个不同的表,其中 id 是为计划自动生成的,我正在尝试根据临时将计划 A 更新为计划 B表(像临时表有新的计划键),所以我创建了一个游标 C1 来动态读取所有新键,并分别在 12 个更新 12 个表中的计划键的程序中更新。我的查询是我不知道如何从所有 12 个表中进行回滚 @BobJarvis 就像假设在更新 alltables 中的某些东西并不顺利然后我必须执行回滚并删除插入的查询并重新更新查询以回滚。另外我如何在这里处理异常。我是不知道通过 PL/SQL 执行的 exc,因此需要建议,例如如何将其包含在所有 12 个表中的插入和更新查询中。 请不要使用印度语,如lakh 【参考方案1】:

您的代码看起来很混乱。要在 PL/SQL 中练习异常处理 - 尝试在开始、异常和结束块中编写 sql 查询。您也可以根据数据的需要在循环中执行此操作。

DECLARE
   lv_qry varchar2(100):=NULL;
   lv_param1 varchar2(100):=NULL;
   lv_param2 varchar2(100):=NULL;
BEGIN
   lv_qry:=''; --your or update query 
   EXECUTE IMMEDIATE lv_qry into lv_param1 using lv_param2; --Bind the variable 'optional'
   COMMIT;
 EXCEPTION
    WHEN others THEN
      DBMS_OUTPUT.PUT_LINE(sqlerrm);
      ROLLBACK;
 END;

【讨论】:

您的示例代码使用动态 SQL。原始问题中没有提到动态 SQL。如果您故意建议 OP 使用动态 SQL,那么请扩展您的问题以解释 OP 将从这种方法中获得什么好处。否则,请编辑您的回复以更接近 OP 发布的代码。 @APC 是的,我正在尝试使用动态 SQL。只是简单介绍一下,我总共有 12 个不同的表,其中 id 是为计划自动生成的,我正在尝试将计划 A 更新为计划 B临时表(就像临时表有新的计划键),所以我创建了一个游标 C1 来动态读取所有新键,并分别在 12 个更新 12 个表中的计划键的程序中更新。我的查询是我不知道如何从所有 12 个表中进行回滚。 @APC 就像假设在所有表中更新某些东西并不顺利然后我必须执行回滚并删除插入的查询并重新更新查询以回滚。另外我该如何处理这里的异常。我是不知道通过 PL/SQL 执行的 exc,因此需要建议,例如如何将其包含在所有 12 个表中的插入和更新查询中。 @Atul Kr Dey 谢谢。我有两个问题1.当我编写 12 种不同的程序以在 12 个不同的表中更新/插入并在所有程序的执行结束时编写 COMMIT 时,应该存在异常块全部12个块,或者最后在COMMIT.2之后。所有过程中的insert和update语句可以有什么样的异常?我们可以直接使用oracle的预定义异常吗? @lisa14 - 请编辑您的问题,明确您想要实现的目标以及您希望我们提供的服务。评论是针对,嗯,cmets:大多数阅读您的问题的人可能不会向下滚动以阅读答案中的 cmets 线程。【参考方案2】:

只要在单个事务中执行所有更新等,单个 ROLLBACK 就会回滚事务中所做的所有更改。当没有事务生效时执行 DML 操作(SELECT、INSERT、UPDATE、MERGE、DELETE)时,事务会自动启动;您也可以使用 SET TRANSACTION 语句启动一个。

【讨论】:

以上是关于PL/SQL 中的异常处理和回滚的主要内容,如果未能解决你的问题,请参考以下文章

文件错误?带有未处理异常的子程序不执行任何回滚?

PL/SQL 过程中的异常处理

PL/SQL 中的异常处理。 [关闭]

PLSQL——05异常处理

处理过程 PL/SQL 的异常

如何以不同的方式处理 PL/SQL 中的不同异常?