DBMS_ERRLOG 包提供一种方法给指定表创建对应的错误日志表。
创建错误日志表的方法有两种,一是通过 DBMS_ERRLOG 包中的 CREATE_ERROR_LOG 来创建,二是通过 SQL 语法手动创建。因为使用 DBMS_ERRLOG 包创建错误日志表简单易行,建议用户使用方法一。
42.1 相关方法
给指定表创建对应的错误日志表。不支持指定表中含有列类型为 LONG、CLOB、 BLOB、 BFILE 的列。也不支持指定的表中和要创建的错误日志表含有同名列。
语法如下:
PROCEDURE CREATE_ERROR_LOG(
DML_TABLE_NAME IN VARCHAR,
ERR_LOG_TABLE_NAME IN VARCHAR DEFAULT NULL,
ERR_LOG_TABLE_OWNER IN VARCHAR DEFAULT NULL,
ERR_LOG_TABLE_SPACE IN VARCHAR DEFAULT NULL,
SKIP_UNSUPPORTED IN BOOLEAN DEFAULT FALSE
);
参数详解
● DML_TABLE_NAME 输入参数, 错误日志记录表所基于的数据库表,支持以前缀形式指定其他用户的表。
● ERR_LOG_TABLE_NAME 输入参数, 用户创建的错误日志记录表的名字,默认使用数据库表名加上前缀’ERR$_’。错误日志记录表结构如下:
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | DM_ERR_NUMBER$ | INTEGER | 错误码 |
2 | DM_ERR_MESG$ | VARCHAR(2000) | 错误信息 |
3 | DM_ERR_ROWID$ | ROWID | 保存出错的行号,insert 时为空值 |
4 | DM_ERR_OPTYP$ | VARCHAR(2) | 出错的 dml 类型, I 表示插入, U 表示更新, D 表示删除 |
5 | DM_ERR_TAG$ | VARCHAR(2000) | log errors 语法(expression)设定的值, 未设置时为空 |
通过 SQL 语法手动创建错误日志表(例如,表名为 LOG_T1)。为了减少出错环节,不推荐用户自己手动创建。
create table LOG_T1(
DM_ERR_NUMBER$ INTEGER,
DM_ERR_MESG$ VARCHAR(2000),
DM_ERR_ROWID$ ROWID,DM_ERR_OPTYP$ VARCHAR(2),
DM_ERR_TAG$ VARCHAR(2000));
● ERR_LOG_TABLE_OWNER 输入参数,错误日志记录表的拥有者,默认使用当前连接的用户。
● ERR_LOG_TABLE_SPACE 输入参数,错误日志记录表所在的表空间,需要有权限,默认使用当前用户使用的表空间。
● SKIP_UNSUPPORTED 输入参数,设置为 TRUE 时,列类型不支持的将会被跳过并且不会添加到错误日志记录表,设置为 FALSE 时,一个不支持的列类型将会引发过程中断,默认为 FALSE。
42.2 使用说明
- 使用该包需要有包执行权限,表的操作权限,建表权限。
- 支持对日志表进行 I/D/U 操作。
- 暂时不支持对视图建错误日志表。
- 暂时不支持对系统表建错误日志表。
- 暂时不支持临时表和 HUGE 表。
- 暂时不支持批量绑定参数执行*<*log erros> 语法。
- 只有错误发生在 I/D/U 的自身操作符执行期间才会记录日志。
- 部分错误在进行错误日志记录时无法登记数据,如字符串转换出错。
- 暂不支持错误日志表中存在二级索引、约束、触发器。
- 暂时不支持 INSERT ALL 语句中使用*<*log erros> 语法。
- 虚拟列暂不进行记录数据。
- 暂时不支持 DBLINK。
42.3 使用错误日志表
在数据插入语句、数据修改语句或数据删除语句的尾部使用*<*log errors>,可以将错误操作生成错误记录,登记到错误日志表中。
log errors 语法:
<数据插入语句><log errors>;
<数据修改语句><log errors>;
<数据删除语句><log errors>;
<log errors>::=LOG ERRORS [INTO <表名>][(<expression>)] REJECT LIMIT <UNLIMITED | <错误行数>>
<数据插入语句>::=请参考《DM8_SQL语言使用手册》第5.1节
<数据修改语句>::=请参考《DM8_SQL语言使用手册》第5.2节
<数据删除语句>::=请参考《DM8_SQL语言使用手册》第5.3节
参数详解
● [INTO < 表名 >] 错误日志表的表名。缺省使用的是默认错误日志表名。
● *<expression> 是一个表达式,为错误日志记录的一个标记,即每一行错误日志会有一列存储此列表达式的值,该 <*expression> 需要是字符串或者是可以转换为字符串的内容。
● REJECT LIMIT <UNLIMITED | < 错误行数 >> 指定允许的最大错误行数。UNLIMITED 表示没有限制;< 错误行数 > 指定的允许的最大错误行数,取值(0~ 2147483647),超过此值将回滚 DML 操作,但仍保留已经生成的错误日志。错误日志表生成记录后,不会因为 DML 语句的回滚而回滚,也不会因为基表被删除而同步被删除。其中,空间不足导致的回滚,不会在错误日志表中记录回滚记录。 针对不同的 DML 操作,错误日志表中记录的错误类型如下表所示:
DML 操作 | 字符串转换出错 | 违反唯一约束条件 | 不允许 NULL 值 | 数据超过数据类型限制 | 分区列更新将引起分区的更 | 插入值不满足分区范围 |
---|---|---|---|---|---|---|
INSERT | 支持 | 支持 | 支持 | 支持 | × | 支持 |
UPDATE | × | × | 支持 | 支持 | 支持 | × |
DELETE | × | × | × | × | × | × |
注:符号“×”表示错误日志表中暂不支持记录该报错信息
42.4 举例说明
使用包内的过程和函数之前,如果还未创建过系统包,请先调用系统过程 SP_CREATE_SYSTEM_PACKAGES 创建系统包。
SP_CREATE_SYSTEM_PACKAGES(1,'DBMS_ERRLOG');
首先,创建数据库表 t1,并使用 DBMS_ERRLOG 为 t1 创建一个错误日志表。同时插入 3 条数据。
create table t1 (id int primary key,name varchar(20));
begin
DBMS_ERRLOG.CREATE_ERROR_LOG('T1','LOG_T1');
end;
/
insert into t1 values(1, 'a');
insert into t1 values(2, 'b');
insert into t1 values(10, 'j');
其次,在插入数据的时候使用*<*log errors>。为 t1 插入 20 条数据,其中有三条是违反了唯一性约束的。
begin
for i in 1..20 loop
insert into t1 values(i,i) LOG ERRORS INTO LOG_T1 ('INSERT ERROR') REJECT LIMIT UNLIMITED;
end loop;
commit;
end;
/
然后,查看日志信息表。
select * from LOG_T1;
查询结果如下:
行号 | DM_ERR_NUMBER** | **DM_ERR_MESG | DM_ERR_ROWID** | **DM_ERR_OPTYPE | DM_ERR_TAG$ | ID | NAME | ||
---|---|---|---|---|---|---|---|
1 | -6602 | 违反表[T11]唯一性约束 | AAAAAAAAAAAAAAAAAE | I | INSERT ERROR | 1 | 1 |
2 | -6602 | 违反表[T11]唯一性约束 | AAAAAAAAAAAAAAAAAF | I | INSERT ERROR | 2 | 2 |
3 | -6602 | 违反表[T11]唯一性约束 | AAAAAAAAAAAAAAAAAN | I | INSERT ERROR | 10 | 10 |
可见,LOG_T1 中记录了插入失败的数据以及相关信息。
select count(*) from t1;
查询结果为:20。
可见,t1 中插入了全部未出错的数据。之前的 3 条和后来批量插入的 17 条。