ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 浅谈例外表的应用

浅谈例外表的应用

原创 Linux操作系统 作者:to_be_dba 时间:2012-09-25 12:42:06 0 删除 编辑

实验:例外表的使用

当我们用程序向表中插入大量数据时,可能有几条是不满足条件的,这时候我们可能希望满足条件的数据被执行,而程序不报错。不满足条件的数据呢,可能想把它放到其他地方,以备查验。
oracle为我们提供了一种简单方便的实现方法,通过内部的包即可将例外内容收集,并保证事务正常结束。
我们来看实验:

环境:oracle 10g+windows2003
首先创建了一个测试表:
create table t1 as select object_name,object_type from dba_objects where 1=2;
然后我们给其添加约束:alter table t1 modify object_type not null;
这时,如果直接插入object_type为空的记录就会报错:

SQL> insert into T1 (OBJECT_NAME, OBJECT_TYPE)
  2  values ('ICOL$', '');

insert into T1 (OBJECT_NAME, OBJECT_TYPE)
values ('ICOL$', '')

ORA-01400: 无法将 NULL 插入 ("SCOTT"."T1"."OBJECT_TYPE")

下面用dbms_errlog包来捕获例外:
--创建例外捕获表T1_ERROR
begin
dbms_errlog.create_error_log('T1','T1_ERROR','SCOTT');
end;
/

执行成功后我们来插入几条数据:
begin
insert into T1 (OBJECT_NAME, OBJECT_TYPE)
values ('ICOL$', '') log errors into t1_error reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)
values ('I_USER1', 'TABLE')log errors into t1_error reject limit unlimited;
commit ; 
end;
/

可以看到不满足条件的记录被插入到了例外捕获表中:
SQL> select * from t1_error;

ORA_ERR_NUMBER$ ORA_ERR_MESG$                                                                    ORA_ERR_ROWID$                                                                   ORA_ERR_OPTYP$ ORA_ERR_TAG$                                                                     OBJECT_NAME                                                                      OBJECT_TYPE
--------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
           1400 ORA-01400: 无法将 NULL 插入 ("SCOTT"."T1"."OBJECT_TYPE")                                                                                                          I                                                                                               ICOL$
                                                                                                                       
例外捕获表的结构为:                             
SQL> desc t1_error;
Name            Type           Nullable Default Comments
--------------- -------------- -------- ------- --------
ORA_ERR_NUMBER$ NUMBER         Y                        
ORA_ERR_MESG$   VARCHAR2(2000) Y                        
ORA_ERR_ROWID$  UROWID(4000)   Y                        
ORA_ERR_OPTYP$  VARCHAR2(2)    Y                        
ORA_ERR_TAG$    VARCHAR2(2000) Y                        
OBJECT_NAME     VARCHAR2(4000) Y                        
OBJECT_TYPE     VARCHAR2(4000) Y   

以上列值还是比较好理解的,ORA_ERR_NUMBER$是oracle例外代码;ORA_ERR_MESG$是例外提示信息;ORA_ERR_ROWID$是进行更新、删除操作时产生例外的列rowid;ORA_ERR_OPTYP$的取值有I(insert)、U(update)、D(delete);

当执行update语句时,
begin
update t1 set object_type='' where object_name='CON$' log errors into t1_error reject limit unlimited;
update t1 set object_type='111' where object_name='UNDO$' log errors into t1_error reject limit unlimited;
commit ;
end;
/

SQL> select * from t1_error t;

ORA_ERR_NUMBER$ ORA_ERR_MESG$                                                                    ORA_ERR_ROWID$                                                                   ORA_ERR_OPTYP$ ORA_ERR_TAG$                                                                     OBJECT_NAME                                                                      OBJECT_TYPE
--------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
           1407 ORA-01407: 无法更新 ("SCOTT"."T1"."OBJECT_TYPE") 为 NULL                         AAAM24AAEAAAGMkAAC                                                               U                                                                                               CON$
                                                                             
ORA_ERR_ROWID$的值对应的是产生例外的待修改的列rowid。


在创建时我们并不需要去指定该表的结构,自动包含了例外代码、例外信息、例外行rowid、例外类型、标志以及所对应表的所有列。

确实很强大。但还不是全部。

试想,如果表的字段比较多,不需要在例外捕获表中重复写入那么多字段,那么只包含有约束的行就行啦,来看实验:

 
SQL> truncate table t1;

Table truncated

SQL> create  table error_show(ora_err_number$ number,ora_err_mesg$ varchar2 (200),object_type varchar2(200));

Table created

SQL>

begin
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('ICOL$', '') log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('I_USER1', 'TABLE')log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('', 'TABLE') log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('UNDO$', 'TABLE') log errors into error_show reject limit unlimited;
/*update t1 set object_type='' where object_name='CON$' log errors into t1_error reject limit unlimited;
update t1 set object_type='111' where object_name='UNDO$' log errors into t1_error reject limit unlimited;*/
commit ;
end;

ORA-38900: 缺失必需的列 "ORA_ERR_ROWID$" (例外日志表 "ERROR_SHOW")
ORA-06512: 在 line 2


后面有尝试缺少ORA_ERR_NUMBER$列,报错相似。因此得出结论:当使用自定义例外表时,表中还是必须包含oracle指定的列:ORA_ERR_NUMBER$ NUMBER、ORA_ERR_MESG$、ORA_ERR_ROWID$、ORA_ERR_OPTYP$和ORA_ERR_TAG$的,我们可以修改的只是其他的列。仔细思考一下,由于例外表创建时并不知道会产生哪类错误;oracle需要保证所有的例外都被显示出来,而这五列保证了错误显示的完整性。

当然,我们是可以只包含以上这五列的。

 

SQL> drop table error_show;

Table dropped

SQL> create  table error_show(ORA_ERR_NUMBER$ NUMBER,ORA_ERR_MESG$   VARCHAR2(2000),ORA_ERR_ROWID$  UROWID(4000),
ORA_ERR_OPTYP$  VARCHAR2(2),ORA_ERR_TAG$    VARCHAR2(2000));

Table created

执行匿名块:
begin
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('ICOL$', '') log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('I_USER1', 'TABLE')log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('', 'TABLE') log errors into error_show reject limit unlimited;
insert into T1 (OBJECT_NAME, OBJECT_TYPE)values ('UNDO$', 'TABLE') log errors into error_show reject limit unlimited;
/*update t1 set object_type='' where object_name='CON$' log errors into t1_error reject limit unlimited;
update t1 set object_type='111' where object_name='UNDO$' log errors into t1_error reject limit unlimited;*/
commit ;
end;
/

SQL>

PL/SQL procedure successfully completed

当只定义了oracle默认的5列作为例外表时,可以将不同表的例外都插入一个例外表中。从ora_err_mesg$列可以区分出是哪个表报错的。

例如,将t表和t1表的例外数据都放入error_show表,查询结果为:
SQL> select * from error_show;

ORA_ERR_NUMBER$ ORA_ERR_MESG$                                                                    ORA_ERR_ROWID$                                                                   ORA_ERR_OPTYP$ ORA_ERR_TAG$
--------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------- --------------------------------------------------------------------------------
           1400 ORA-01400: 无法将 NULL 插入 ("SCOTT"."T1"."OBJECT_TYPE")                                                                                                          I             
           1400 ORA-01400: 无法将 NULL 插入 ("SCOTT"."T"."OBJECT_NAME") 


总的来说,例外表的功能还是蛮强大的,值得好好利用,也确实能为我们减轻很多工作负担。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26451536/viewspace-744994/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 外部表的使用
请登录后发表评论 登录
全部评论

注册时间:2011-11-23

  • 博文量
    170
  • 访问量
    484882