yangtingkun
===========================================================
获取导致导入失败的数据(二)
===========================================================

前不久从一个数据库执行导出操作时报错,通过直接路径方式跳过后,导入时候再次报错。推测是由于源数据库出现的异常导致表中数据超过表定义的精度。

由于源数据库中错误记录已经被删除,因此只能想办法从导出的dmp文件中获取错误记录。

导出、导入过程的描述可以参考:

EXP9R2上导出时报错ORA-3113ORA-24324http://yangtingkun.itpub.net/post/468/460647

EXP9R2上导出时报错ORA-3113ORA-24324(二):http://yangtingkun.itpub.net/post/468/460831

上一篇通过触发器的方式没有获取到具体的错误数据,这篇继续修正方法继续找出异常的数据:

获取导致导入失败的数据:http://yangtingkun.itpub.net/post/468/461401

BEFORE触发器修正数据错误:http://yangtingkun.itpub.net/post/468/461506


由于上一篇的诸多测试已经将各个表的结构修改的比较混乱,下面重建所有的测试结构:

SQL> DROP TABLE SHGOV_ORDER_BAK;

表已丢弃。

SQL> DROP TABLE SHGOV_ORDER;

表已丢弃。

SQL> CONN / AS SYSDBA已连接。
SQL> DROP TRIGGER FIND_ERR_SQL;

触发器已丢弃

SQL> DROP TABLE T_LOG;

表已丢弃。

利用导入工具重建SHGOV_ORDER表:

[oracle@bjtest data]$ imp test/test file=jg080424.dmp tables=shgov_order buffer=2048000 ignore=y rows=n

Import: Release 9.2.0.4.0 - Production on 星期五 5 9 17:48:37 2008

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

连接到: Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

经由常规路径导出由EXPORT:V09.02.00创建的文件

警告: 此对象由 SHGOV 导出, 而不是当前用户

已经完成ZHS16GBK字符集和AL16UTF16 NCHAR 字符集中的导入
.
正在将SHGOV的对象导入到 TEST
IMP-00009:
导出文件异常结束
成功终止导入,但出现警告。

下面建立用来存储触发器插入记录的表:

SQL> CREATE TABLE SHGOV_ORDER_BAK AS
2 SELECT TRADE_RATE, ORDER_AMOUONT, SEND_AMOUNT, RECEIVE_AMOUNT,
3 UNIT_PRICE, MAX_PRICE, MIN_PRICE, PRICE_RATE
4 FROM SHGOV_ORDER;

表已创建。

SQL> CREATE TABLE T_LOG (EXECUTE_DATE DATE, SQL_STATMENT CLOB);

表已创建。

怀疑问题出在NUMBER类型的字段上,因此目标表只包含了NUMBER类型的字段,而且为了方便查询,将系统触发器的日志也放到当前用户下。

由于采用静态SQL的方式,从系统触发器获取的SQL语句都是绑定变量的形式,没有办法看到引发错误的数据,因此触发器修改一下,改为动态SQL的方式,希望采用这种方式可以获取到错误的数据。

SQL> CREATE OR REPLACE TRIGGER FIND_ERR_SQL
2 BEFORE INSERT ON SHGOV_ORDER
3 FOR EACH ROW
4 DECLARE
5 PRAGMA AUTONOMOUS_TRANSACTION;
6 BEGIN
7 EXECUTE IMMEDIATE 'INSERT INTO SHGOV_ORDER_BAK
8 (
9 TRADE_RATE, ORDER_AMOUONT, SEND_AMOUNT, RECEIVE_AMOUNT,
10 UNIT_PRICE, MAX_PRICE, MIN_PRICE, PRICE_RATE
11 )
12 VALUES
13 (
14 ' || :NEW.TRADE_RATE || ', ' || :NEW.ORDER_AMOUONT || ', '
15 || :NEW.SEND_AMOUNT || ', ' || :NEW.RECEIVE_AMOUNT || ', '
16 || :NEW.UNIT_PRICE || ', ' || :NEW.MAX_PRICE || ', '
17 || :NEW.MIN_PRICE || ', ' || :NEW.PRICE_RATE || ')';
18 COMMIT;
19 END;
20 /

触发器已创建

最后建立系统触发器,并对原有代码进行简单的调整,去掉了对1438错误的判断,这样发生任何的错误都可以捕获。

SQL> CONN / AS SYSDBA已连接。
SQL> CREATE OR REPLACE TRIGGER FIND_ERR_SQL AFTER SERVERERROR ON DATABASE
2 DECLARE
3 V_SQL_OUT ORA_NAME_LIST_T;
4 V_NUM NUMBER;
5 V_SQL_STATMENT VARCHAR2(32767);
6 BEGIN
7 V_NUM := ORA_SQL_TXT(V_SQL_OUT);
8 FOR I IN 1 .. V_NUM LOOP
9 V_SQL_STATMENT := V_SQL_STATMENT || V_SQL_OUT(I);
10 END LOOP;
11 INSERT INTO TEST.T_LOG (EXECUTE_DATE, SQL_STATMENT)
12 VALUES (SYSDATE, V_SQL_STATMENT);
13 END;
14 /

触发器已创建

由于IMP采用绑定变量的方式,捕获IMP的错误没有意义,而且由于Oracle会先验证插入数据的合法性,然后调用BEFORE触发器,因此导入错误记录时,BEFORE触发器是不会被触发的。所以,这里需要修改一下SHGOV_ORDER表的数值类型,将其转化为NUMBER类型,这样让精度问题出现在触发器中,使得系统触发器可以捕获这个错误。

SQL> ALTER TABLE SHGOV_ORDER MODIFY
2 (
3 TRADE_RATE NUMBER,
4 UNIT_PRICE NUMBER,
5 MAX_PRICE NUMBER,
6 MIN_PRICE NUMBER,
7 PRICE_RATE NUMBER
8 );

表已更改。

下面执行导入:

[oracle@bjtest data]$ imp test/test file=jg080424.dmp tables=shgov_order buffer=2048000 ignore=y

Import: Release 9.2.0.4.0 - Production on 星期五 5 9 18:15:08 2008

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

连接到: Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

经由常规路径导出由EXPORT:V09.02.00创建的文件

警告: 此对象由 SHGOV 导出, 而不是当前用户

已经完成ZHS16GBK字符集和AL16UTF16 NCHAR 字符集中的导入
.
正在将SHGOV的对象导入到 TEST
. .
正在导入表
"SHGOV_ORDER"
IMP-00058:
遇到 ORACLE 错误
917
ORA-00917:
缺少逗号

ORA-06512:
"TEST.FIND_ERR_SQL", line 4
ORA-04088:
触发器 'TEST.FIND_ERR_SQL' 执行过程中出错

IMP-00028:
上一个表的部分导入已回退: 回退 31322
IMP-00009:
导出文件异常结束成功终止导入,但出现警告。

查看记录SQL的结果:

SQL> CONN TEST/TEST已连接。
SQL> SET LONG 100000
SQL> SELECT SQL_STATMENT FROM T_LOG;

SQL_STATMENT
--------------------------------------------------------------------------------
CREATE TABLE "SHGOV_ORDER" ("ORDER_ITEM_ID" CHAR(24) NOT NULL ENABLE, "PLAT_ID"
CHAR(24), "PRODUCT_ID" CHAR(24), "CODE" VARCHAR2(50), "C_NAME_CHN" VARCHAR2(300)
.
.
.
ANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1) TABLESPA
CE "SH_GOV" LOGGING NOCOMPRESS

CREATE TABLE "SHGOV_ORDER" ("ORDER_ITEM_ID" CHAR(24) NOT NULL ENABLE, "PLAT_ID"
CHAR(24), "PRODUCT_ID" CHAR(24), "CODE" VARCHAR2(50), "C_NAME_CHN" VARCHAR2(300)
.
.
.
ATE, "SENDE_DATE" DATE, "PRICE_RATE" NUMBER(12, 3)) PCTFREE 10 PCTUSED 40 INITR
ANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1)
LOGGING NOCOMPRESS

INSERT /*+NESTED_TABLE_SET_REFS+*/ INTO "SHGOV_ORDER" ("ORDER_ITEM_ID", "PLAT_ID
", "PRODUCT_ID", "CODE", "C_NAME_CHN", "MEDICAL_ID", "MEDICAL_CODE", "TRADE_NAME
", "USE_UNIT", "USED_NAME", "MANUFACTURE_ID", "MANUFACTURE_NAME", "MANUFACTURE_A
BBR", "M_SPELL_ABBR", "STAND_RATE", "SPEC", "E_NAME_CHN", "JX_NAME_CHN", "WRAP_N
AME", "TAX_PRICE", "NATIONAL_RETAIL_PRICE", "TRADE_RATE", "MED_INSURE", "ORDER_I
D", "ORDER_AMOUONT", "SEND_AMOUNT", "RECEIVE_AMOUNT", "UNIT_PRICE", "SOURCE_TYPE
", "MAX_PRICE", "HIS_NAME", "HIS_ABBR", "HIS_ID", "DEALER_NAME", "DEALER_ID", "D
EALER_ABBR", "MIN_PRICE", "SENDER_NAME", "SENDER_ID", "SENDER_ABBR", "CREATE_DAT
E", "SENDE_DATE", "PRICE_RATE") VALUES (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10,
:11, :12, :13, :14, :15, :16, :17, :18, :19, :20, :21, :22, :23, :24, :25, :26,
:27, :28, :29, :30, :31, :32, :33, :34, :35, :36, :37, :38, :39, :40, :41, :42,
:43)

看来即使是让触发器报错,捕获到的最终出错SQL也是导入的SQL语句,看来试图利用触发器捕获异常数据的方法,基本上是行不通的。

yangtingkun 发表于:2008.05.09 22:53 ::分类: ( ORACLE ) ::阅读:(219次) :: 评论 (0)

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...