通过前面的处理还剩ORA错误21个,IMP错误202个。

检查日志文件发现,大部分IMP错误信息来自OLAPSYS用户的创建视图过程。

检查第一个发出告警的视图,发现创建脚本包括了SYS用户的表。我们知道,使用全库导入Oracle会自动忽略SYS或者SYSTEM方案下的对象权限。这个问题的具体描述参见:http://yangtingkun.itpub.net/post/468/220918

而在导入之前删除了OLAPSYS用户,因此OLAPSYS用户不在拥有SYS对象的访问权限,而导入又忽略了这些权限,于是产生了错误。

因此,尝试重建用户时保留用户的权限。

SQL> DECLARE
2 TYPE T_VARCHAR_TAB IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
3 V_PRIVS_STR T_VARCHAR_TAB;
4 V_ROLE_STR T_VARCHAR_TAB;
5 V_DROP_STR VARCHAR2(32767);
6 V_CREATE_STR VARCHAR2(32767); 
7 BEGIN
8 FOR I IN (SELECT USERNAME FROM DBA_USERS WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'WMSYS', 'ORDSYS')) LOOP
9 SELECT DBMS_METADATA.GET_DDL('USER', I.USERNAME) INTO V_CREATE_STR FROM DUAL;
10 
11 SELECT 'GRANT ' || PRIVILEGE || ' ON ' || OWNER || '.' || TABLE_NAME || ' TO ' || GRANTEE 
12 BULK COLLECT INTO V_PRIVS_STR
13 FROM DBA_TAB_PRIVS WHERE GRANTEE = I.USERNAME;
14 
15 SELECT 'GRANT ' || GRANTED_ROLE || ' TO ' || GRANTEE
16 BULK COLLECT INTO V_ROLE_STR
17 FROM DBA_ROLE_PRIVS WHERE GRANTEE = I.USERNAME;
18 
19 SELECT 'DROP USER ' || I.USERNAME || ' CASCADE' INTO V_DROP_STR FROM DUAL;
20 
21 EXECUTE IMMEDIATE V_DROP_STR;
22 EXECUTE IMMEDIATE V_CREATE_STR;
23 FOR I IN 1..V_PRIVS_STR.COUNT LOOP
24 BEGIN
25 EXECUTE IMMEDIATE V_PRIVS_STR(I);
26 EXCEPTION
27 WHEN OTHERS THEN
28 NULL;
29 END;
30 END LOOP;
31 FOR I IN 1..V_ROLE_STR.COUNT LOOP
32 EXECUTE IMMEDIATE V_ROLE_STR(I);
33 END LOOP;
34 END LOOP;
35 END;
36 /

PL/SQL 过程已成功完成。

执行导入操作后发现,OLAPSYS用户的错误仍然存在,但是错误数目已经减少。IMP错误减少到了127个。

仔细检查OLAPSYS用户的错误,发现是由于参考了OLAPSYS本身的包造成的,由于Oracle导入表在导入包之前,因此导致了这个错误。在导入结束后,这些发生告警的视图都是可以访问的。

原则上没有必要再去追究这些告警,不过本文档的目的就是尽量的加上错误和警告,因此这里选择了手工提前创建包的方法:

SQL> ALTER SESSION SET CURRENT_SCHEMA=OLAPSYS;

会话已更改。

SQL> @?/cwmlite/admin/oneputlp.pls

程序包已创建。

SQL> @?/cwmlite/admin/cwm2asec.pls

程序包已创建。

没有错误。
SQL> ALTER SESSION SET CURRENT_SCHEMA=SYS;

会话已更改。

然后执行导入操作,效果很令人惊喜,ORA错误虽然没有变仍然是21个,但是IMP错误已经减少到了17个。

OLAPSYS用户已经没有在报任何的错误和告警信息了。

WKSYS用户下的错误和OLAPSYS的类型,加上下面的代码后错误消失:

SQL> CREATE OR REPLACE FUNCTION WKSYS.WK$USER
2 RETURN VARCHAR2
3 AS
4 BEGIN
5 return nvl(sys_context('WK$CONTEXT', 'USER'),
6 sys_context('USERENV', 'SESSION_USER'));
7 END;
8 /

函数已创建。

SQL> CREATE OR REPLACE FUNCTION WKSYS.WK$USERID
2 RETURN NUMBER
3 AS
4 FUNCTION GET_DATABASE_USERID RETURN VARCHAR2 AS
5 ID NUMBER;
6 BEGIN
7 SELECT USER# INTO ID FROM SYS.USER$
8 WHERE NAME = SYS_CONTEXT('USERENV','SESSION_USER');
9 RETURN ID;
10 END;
11 BEGIN
12 RETURN NVL(TO_NUMBER(SYS_CONTEXT('WK$CONTEXT','USERID')),
13 GET_DATABASE_USERID);
14 END;
15 /

函数已创建。

SQL> CREATE TABLE WKSYS.WK$SYS_PRIV (
2 SP_USERID NUMBER,
3 SP_USER VARCHAR2(100),
4 SP_OPTIONS VARCHAR2(10),
5 PRIMARY KEY (SP_USERID, SP_USER) USING INDEX TABLESPACE DRSYS 
6 ) TABLESPACE DRSYS;

表已创建。

SQL> CREATE OR REPLACE FUNCTION WKSYS.WK$IS_ADMIN(
2 WITH_OPTION IN VARCHAR2 DEFAULT NULL
3 )
4 RETURN NUMBER
5 AS
6 CUSER VARCHAR2(200) := WK$USER;
7 CUID NUMBER := WK$USERID;
8 BEGIN
9 IF (CUID >= 0 AND CUSER IN ('WKSYS', 'SYS')) THEN
10 IF (WITH_OPTION IS NULL OR INSTR('G', WITH_OPTION) > 0) THEN
11 RETURN 1;
12 END IF;
13 ELSIF (CUID = -2 AND CUSER IN ('IAS_ADMIN')) THEN
14 IF (WITH_OPTION IS NULL OR INSTR('G', WITH_OPTION) > 0) THEN
15 RETURN 1;
16 END IF;
17 ELSE
18 FOR C IN (SELECT SP_USERID FROM WK$SYS_PRIV
19 WHERE SP_USER = CUSER AND SP_USERID = CUID AND
20 (WITH_OPTION IS NULL OR
21 INSTR(SP_OPTIONS, WITH_OPTION) > 0))
22 LOOP
23 RETURN 1;
24 END LOOP;
25 END IF;
26 RETURN 0;
27 END;
28 /

函数已创建。

至此,ORA错误还是21个。IMP错误还剩15个。