减少全库导入时发生的错误(三)

 通过前面的处理,现在全库导入还剩下ORA-错误还有47个,IMP-错误252个。

通过检查发现目前出现的错误中,有很多是由于导入操作时,OBJECT ID不一致造成的。解决这个错误有三种方法。

一、通过在目标库中提前安装导入对象的OID创建对象,然后再导入;

二、通过修改DMP文件中的OID标识,不过这种办法只对本库中已经存在的对象有效,而且可能会破坏dmp文件;

三、使用IMP的参数TOID_NOVALIDATE,使Oracle在执行导入的时候跳过对OID的判断。

相比较之下,第三种方法的工作量更小一些,于是尝试在导入的时候增加TOID_NOVALIDATE参数:

imp "sys as sysdba" file=testmv_full.dmp full=y buffer=20480000 ignore=y log=testmv_full.log toid_novalidate=(sys.aq$_jms_userproparray, sys.aq$_jms_text_message, system.repcat$_object_null_vector, mdsys.sdo_ordinate_array, mdsys.sdo_elem_info_array, mdsys.sdo_geometry, ordsys.orddoc, ordsys.ordaudio, ordsys.ordvideo, ordsys.ordimagesignature, ordsys.ordimage)

通过这种方法导入后,错误进一步减少,ORA错误35个,IMP错误247个。

但是观察日志发现,最后8TYPE使用了TOID_NOVALIDATE参数仍然报错。前面几个TYPE使用TOID_NOVALIDATE参数后已经生效了,看来TOID_NOVALIDATE参数是有效的。再观察错误信息:

IMP-00060: 警告跳过表 "OE"."WAREHOUSES",因为对象类型 "MDSYS"."SDO_ORDINATE_ARRAY" 不存在或具有不同的标识符

看来问题的原因是MDSYS.SDO_ORDINATE_ARRAY类型还不存在。

这里需要按照第一种方法,把对象先建立上去。首先在导出数据库查询对象的OID

SQL> SELECT TYPE_NAME, TYPE_OID FROM DBA_TYPES 
2 WHERE OWNER = 'MDSYS' AND TYPE_NAME IN ('SDO_ORDINATE_ARRAY', 'SDO_ELEM_INFO_ARRAY', 'SDO_GEOMETRY');

TYPE_NAME TYPE_OID
------------------------------ --------------------------------
SDO_ORDINATE_ARRAY 3796C48378FC407AE03400400B407D5F
SDO_ELEM_INFO_ARRAY 3796C48378FD407AE03400400B407D5F
SDO_GEOMETRY 3796C48378FE407AE03400400B407D5F

然后根据这个OID把对象建立在目标数据库上:

SQL> CREATE OR REPLACE TYPE MDSYS.SDO_ORDINATE_ARRAY OID '3796C48378FC407AE03400400B407D5F'
2 AS VARRAY(1048576) OF NUMBER;
3 /

类型已创建。

SQL> CREATE OR REPLACE TYPE MDSYS.SDO_ELEM_INFO_ARRAY OID '3796C48378FD407AE03400400B407D5F'
2 AS VARRAY (1048576) of NUMBER;
3 /

类型已创建。

SQL> CREATE OR REPLACE TYPE MDSYS.SDO_POINT_TYPE AS OBJECT (X NUMBER, Y NUMBER, Z NUMBER);
2 /

类型已创建。

SQL> CREATE OR REPLACE TYPE MDSYS.SDO_GEOMETRY OID '3796C48378FE407AE03400400B407D5F' AS OBJECT (
2 SDO_GTYPE NUMBER,
3 SDO_SRID NUMBER,
4 SDO_POINT SDO_POINT_TYPE,
5 SDO_ELEM_INFO SDO_ELEM_INFO_ARRAY,
6 SDO_ORDINATES SDO_ORDINATE_ARRAY,
7 MEMBER FUNCTION GET_GTYPE
8 RETURN NUMBER DETERMINISTIC,
9 MEMBER FUNCTION GET_DIMS
10 RETURN NUMBER DETERMINISTIC,
11 MEMBER FUNCTION GET_LRS_DIM
12 RETURN NUMBER DETERMINISTIC);
13 /

类型已创建。

SQL> CREATE OR REPLACE TYPE BODY MDSYS.SDO_GEOMETRY IS
2 MEMBER FUNCTION GET_GTYPE
3 RETURN NUMBER IS
4 gtype integer;
5 BEGIN
6 gtype := sdo_gtype MOD 100;
7 return gtype;
8 END;
9 MEMBER FUNCTION GET_DIMS
10 RETURN NUMBER IS
11 dims INTEGER;
12 BEGIN
13 dims := sdo_gtype/1000;
14 return dims;
15 END;
16 
17 MEMBER FUNCTION GET_LRS_DIM
18 RETURN NUMBER IS
19 lrs_dim integer;
20 BEGIN
21 lrs_dim := sdo_gtype/100;
22 lrs_dim := lrs_dim MOD 10;
23 return lrs_dim;
24 END;
25 END;
26 /

类型主体已创建。

SQL> GRANT EXECUTE ON MDSYS.SDO_ORDINATE_ARRAY TO PUBLIC WITH GRANT OPTION;

授权成功。

SQL> GRANT EXECUTE ON MDSYS.SDO_ELEM_INFO_ARRAY TO PUBLIC WITH GRANT OPTION;

授权成功。

SQL> GRANT EXECUTE ON MDSYS.SDO_POINT_TYPE TO PUBLIC WITH GRANT OPTION;

授权成功。

SQL> GRANT EXECUTE ON MDSYS.SDO_GEOMETRY TO PUBLIC WITH GRANT OPTION;

授权成功。

再次执行导入操作,ORA错误还有24个,IMP错误还有213个。

下面ORDSYS用户的对象面临同样的问题,但是ORDSYS用户的TYPE数据比较多,而且创建相对比较复杂,于是考虑在删除用户的时候不删除ORDSYS用户,只将ORDSYS用户表中的数据删除。修改前面删除用户和用户数据的脚本:

SQL> DECLARE
2 TYPE T_VARCHAR_TAB IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
3 V_DROP_STR T_VARCHAR_TAB;
4 V_CREATE_STR T_VARCHAR_TAB; 
5 BEGIN
6 SELECT DBMS_METADATA.GET_DDL('USER', USERNAME) BULK COLLECT INTO V_CREATE_STR
7 FROM DBA_USERS
8 WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'WMSYS', 'ORDSYS');
9 SELECT 'DROP USER ' || USERNAME || ' CASCADE' BULK COLLECT INTO V_DROP_STR 
10 FROM DBA_USERS
11 WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'WMSYS', 'ORDSYS');
12 FOR I IN 1..V_DROP_STR.COUNT LOOP
13 EXECUTE IMMEDIATE V_DROP_STR(I);
14 END LOOP;
15 FOR I IN 1..V_CREATE_STR.COUNT LOOP
16 EXECUTE IMMEDIATE V_CREATE_STR(I);
17 END LOOP;
18 END;
19 /

PL/SQL 过程已成功完成。

SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_CNT NUMBER := 0;
3 V_DEL NUMBER := 0;
4 V_LOOP NUMBER := 0;
5 V_RESULT NUMBER := 0;
6 BEGIN
7 <<LABLE_FOR_LOOP>>
8 FOR I IN (SELECT OWNER || '.' || TABLE_NAME TABLE_NAME FROM DBA_TABLES WHERE OWNER IN ('SYSTEM', 'WMSYS', 'ORDSYS')) LOOP
9 EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || I.TABLE_NAME INTO V_RESULT;
10 IF V_RESULT != 0 THEN
11 BEGIN
12 V_CNT := V_CNT + 1;
13 EXECUTE IMMEDIATE 'DELETE ' || I.TABLE_NAME;
14 V_DEL := V_DEL + 1;
15 EXCEPTION
16 WHEN OTHERS THEN
17 NULL;
18 END;
19 END IF;
20 END LOOP;
21 V_LOOP := V_LOOP + 1;
22 DBMS_OUTPUT.PUT_LINE(V_LOOP || ':' || ' COUNT ' || V_CNT || ', DEL ' || V_DEL);
23 IF V_CNT != V_DEL THEN
24 V_CNT := 0;
25 V_DEL := 0;
26 GOTO LABLE_FOR_LOOP;
27 END IF;
28 END;
29 /
1: COUNT 16, DEL 16

PL/SQL 过程已成功完成。

SQL> COMMIT;

提交完成。

重新执行导入后,所有和TYPE相关的错误消失,至此,还剩ORA错误21个,IMP错误202个。

你可能感兴趣的:(全库导入)