zoukankan      html  css  js  c++  java
  • DBMS_ERRLOG记录DML错误日志(二)

       上一篇简单介绍了DML记录语句的限制,虽然所有的例子都是利用INSERT语句,但是LOG ERRORS语句并没有这个限制,UPDATEDELETEMERGE都可以使用这个语句。下面要说的就是这篇的重点,LOG ERRORS语句的限制。

    不支持的操作:

    违反延迟约束;

    直接路径的INSERT或MERGE语句违反了唯一约束或唯一索引;

    更新操作违反了唯一约束或唯一索引。

    不支持的数据类型:

    比如:LONG、LONG RAW、BLOG、CLOB、NCLOB、BFILE以及各种对象类型。Oracle不支持这些类型的原因也很简单,这些特殊的类型不是包含了大量的记录,就是需要通过特殊的方法来读取,因此Oracle没有办法在SQL处理的时候将对应列的信息写到错误记录表中。

    1.下面我们来看不支持的操作,首先看一下违反延迟约束,

    SQL> ALTER TABLE T1 ADD CONSTRAINT PK_T1_B CHECK (B IS NOT NULL) DEFERRABLE INITIALLY DEFERRED;
    Table altered

    测试语句:

    SQL> INSERT INTO T1 VALUES('21','') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    1 row inserted
    SQL> commit;
    commit
    ORA-02091: 事务处理已回退
    ORA-02290: 违反检查约束条件 (NREI.PK_T1_B)

        由于延迟约束的检查在COMMIT时刻进行,而不是在DML发生的时刻,因此不会利用LOG ERRORS语句将违反结果的记录插入到记录表中,这也是很容易理解的。

    下面看看直接路径插入违反唯一约束的情况:

    SQL> INSERT /*+ APPEND */ INTO T1 SELECT * FROM T2 LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    INSERT /*+ APPEND */ INTO T1 SELECT * FROM T2 LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
    ORA-00001: 违反唯一约束条件 (NREI.PK_T1_A)

    直接路径插入本身就很特殊,在执行过程中会绕过很多常规SQL执行的步骤,因此LOG ERRORS语句对其无效也是可以理解的。

    最后来看看更新语句违反唯一约束的情况:

    SQL> UPDATE T1 SET A='1' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    UPDATE T1 SET A='1' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
    ORA-00001: 违反唯一约束条件 (NREI.PK_T1_A)

        可以看到,如果更新操作导致了唯一约束或唯一索引冲突,也是不会记录到错误记录表中的。至于为什么更新操作会产生这种情况,还没有想明白,不过主键的冲突和其他约束冲突有所区别,Oracle在处理的时候很可能会有所考虑。

    2.下面我们来看不支持的数据类型

    SQL> DROP TABLE ERR_T1 PURGE;
    Table dropped

    SQL> alter table T1 add c clob;

    Table altered
    SQL> EXEC DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI');
    begin DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI'); end;
    ORA-20069: Unsupported column type(s) found: C
    ORA-06512: 在 "SYS.DBMS_ERRLOG", line 234
    ORA-06512: 在 line 1

    可以看到,由于T1表拥有不支持的列,导致创建错误记录表的过程报错,错误提示就是T1表中包含了不支持的列。

    如果手工添加CLOB字段到错误记录表:

    SQL> alter table T1 DROP (c);
    Table altered
    SQL> EXEC DBMS_ERRLOG.CREATE_ERROR_LOG('T1','ERR_T1','NREI');
    PL/SQL procedure successfully completed
    SQL> alter table T1 add c clob;
    Table altered
    SQL> alter table ERR_T1 add c clob;
    Table altered

    执行插入语句:

    SQL> INSERT INTO T1 VALUES('21','21','TEST') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    INSERT INTO T1 VALUES('21','21','TEST') LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
    ORA-38904: LOB 列 "C" 不支持 DML 错误事件记录

    可以看到,Oracle会直接报错。

    SQL> UPDATE T1 SET A='22' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    UPDATE T1 SET A='22' WHERE A='2' LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED
    ORA-38904: LOB 列 "C" 不支持 DML 错误事件记录

    OracleDML并不包含不支持列的数据,Oracle也会报错,说明Oracle是在执行之前检查了错误记录表的数据类型,而不是在执行的时候才去处理。

    SQL> alter table ERR_T1 DROP (c);
    Table altered
    SQL> INSERT INTO T1 VALUES('1','1','TEST' ) LOG ERRORS INTO ERR_T1('ERR_T1')REJECT LIMIT UNLIMITED;
    0 rows inserted

    可以看到,删除错误记录语句所不支持的列后,LOG ERRORS语句反而可以顺利执行,而且无论DML语句是否包括哪些不支持列的数据。





  • 相关阅读:
    PID控制器开发笔记之五:变积分PID控制器的实现
    也说读书
    PID控制器开发笔记之四:梯形积分PID控制器的实现
    PID控制器开发笔记之三:抗积分饱和PID控制器的实现
    PID控制器开发笔记之二:积分分离PID控制器的实现
    PID控制器开发笔记之一:PID算法原理及基本实现
    Linux学习笔记之时间同步the NTP socket is in use, exiting问题
    Python关键点笔记之使用 pyenv 管理多个 Python 版本依赖环境
    K8S学习笔记之二进制部署Kubernetes v1.13.4 高可用集群
    K8S学习笔记之ETCD启动失败注意事项
  • 原文地址:https://www.cnblogs.com/longjshz/p/4286807.html
Copyright © 2011-2022 走看看