异常时将记录插入表中

Posted

技术标签:

【中文标题】异常时将记录插入表中【英文标题】:insert record into table on exception 【发布时间】:2015-02-23 08:03:19 【问题描述】:

这是我的场景:

我想在oracle中写一个程序,有四个表,tab1,tab2,tab3,err。 tab1 在(id number, name varchar(250)) 的两列中有一些数据,而另一些则是空的。

tab2 的架构是

(id number, name varchar(50)), for tab3 (id number, name varchar(250)).

我想将数据从 tab1 插入到 tab2,当出现 name 大于 varchar(50) 等异常时,它会插入 tab3 并将错误消息插入到 err 表中。

因此,tab1 中的所有记录都应该使用异常处理相应地插入到 tab2 和 tab3 中。

这是我尝试但失败的方法。

CREATE OR REPLACE
PROCEDURE exception_handler
IS
  vSqlErr  VARCHAR2(200) ;
  vSqlCode VARCHAR2(5) ;
  id2      NUMBER;
  name2    VARCHAR(250);
BEGIN
  INSERT ALL INTO tab3 VALUES
    (id, name
    )
  SELECT * FROM tab1 t;
EXCEPTION
WHEN OTHERS THEN
  INSERT INTO tab2 VALUES
    (id, name
    );
  vSqlErr  := SUBSTR(sqlerrm, 1, 200) ;
  vSqlCode := SUBSTR(SQLCODE, 1, 5) ;
  INSERT INTO err VALUES
    (vSqlErr, vSqlCode
    ) ;
  COMMIT ;
  RAISE;
END;

【问题讨论】:

我刚接触数据库,所以希望有人帮我做, 创建或替换过程 exception_handler IS vSqlErr Varchar2(200) ; vSqlCode Varchar2(5) ; id2号码;名称2 varchar(250); BEGIN 全部插入 tab3 值(id,name) select * from tab1 t;其他人则插入 tab2 值(id,名称)时的例外情况; vSqlErr := substr(sqlerrm, 1, 200) ; vSqlCode := substr(sqlcode, 1, 5) ;插入错误值(vSqlErr,vSqlCode);犯罪 ;增加;结束; 我已经编辑了你的问题。而且,请在下面查看我的答案。 【参考方案1】:

这只是基于您在问题中的输入的简单演示。最好使用 BULK 处理和 SQL%BULK_EXCEPTIONS。 And don't use WHEN OTHERS blindly.

假设您有一个 EMP 表,并且您在员工姓名上的 check constraint 不超过 5 个字符。有一个EMP_ERR 表可以记录错误值和错误消息。让我们看一个测试用例:

SQL> DROP TABLE emp_new PURGE;

Table dropped.

SQL> CREATE TABLE emp_new AS
  2  SELECT * FROM emp WHERE 1 =2;

Table created.

SQL> ALTER TABLE emp_new ADD CONSTRAINT check_ename CHECK(LENGTH(ename)<=5);

Table altered.

SQL> DROP TABLE emp_err PURGE;

Table dropped.

SQL>
SQL> CREATE TABLE emp_err
  2    (
  3      empno   NUMBER,
  4      ename   VARCHAR2(100),
  5      err_msg VARCHAR2(250)
  6    );

Table created.

SQL> CREATE OR REPLACE
  2  PROCEDURE p
  3    (
  4      v_empno NUMBER,
  5      v_ename VARCHAR2
  6    )
  7  IS
  8    vSqlErr  VARCHAR2(200) ;
  9    vSqlCode VARCHAR2(5) ;
 10    empno2   NUMBER;
 11    ename2   VARCHAR2(250);
 12  BEGIN
 13    INSERT INTO emp_new
 14      (empno, ename
 15      ) VALUES
 16      (v_empno, v_ename
 17      );
 18    COMMIT;
 19  EXCEPTION
 20  WHEN OTHERS THEN
 21    vSqlErr  := SUBSTR(sqlerrm, 1, 200) ;
 22    vSqlCode := SUBSTR(SQLCODE, 1, 5) ;
 23    INSERT
 24    INTO emp_err
 25      (
 26        empno,
 27        ename,
 28        err_msg
 29      )
 30      VALUES
 31      (
 32        v_empno,
 33        v_ename,
 34        vSqlErr
 35        ||' - '
 36        ||vSqlCode
 37      );
 38    COMMIT ;
 39    raise;
 40  END;
 41  /

Procedure created.

让我们使用超过 5 个字符的 ename 值执行 procure,这样会引发错误,我们希望将一行插入到 emp_err 表中。

SQL> exec p(1, 'abcdef');
BEGIN p(1, 'abcdef'); END;

*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CHECK_ENAME) violated
ORA-06512: at "SCOTT.P", line 38
ORA-06512: at line 1

因此,引发了错误。让我们看看它是否记录在错误表中。

SQL> column ename format a10
SQL> column err_msg format a100
SQL> set linesize 150

SQL> select * from emp_err;

     EMPNO ENAME      ERR_MSG
---------- ---------- ----------------------------------------------------------------
         1 abcdef     ORA-02290: check constraint (SCOTT.CHECK_ENAME) violated - -2290

SQL>

我们记录了错误详细信息。

【讨论】:

Kumar 因为我还想在引发异常时将记录插入到第三张表中, 所以????是什么阻止你这样做?我已经给你一个完整的答案。您需要做的就是添加另一个插入语句,如此简单。你要我给你写代码吗?你不能指望有人帮你做作业。我还为您编辑了您的问题。格式化您的代码,添加相关标签。你还有什么期待?你有一个工作测试用例的完整答案。如果对您有帮助,请将其标记为已回答。 抛出异常后如何添加另一个insert语句,将table1的所有记录插入table2,大于varchar(50)的记录全部插入table3 我是如何在代码的第 24 行添加的?问我之前你有没有试过? 我的代码也将错误插入到表中,但是我对如何在引发异常时将记录插入到第三个表中感到困惑,(意味着应该将未插入到 table2 中的记录插入到更大的尺寸表3)

以上是关于异常时将记录插入表中的主要内容,如果未能解决你的问题,请参考以下文章

postgres 将异常错误插入表中

如何避免informix中的锁异常

SQL语句 存在就更新不存在就插入

6.MySQL数据库结构设计

使用 IBAction 插入数据抛出异常

SQL server 一些小结