ORA-00904:"WM_CONCAT":标识符无效
今天客户现场业务甩给我一个报错让处理,ora-00904:"WM_CONCAT":标识符无效。
初步分析了下场景:
前天因为在原先一套库要删除,而他们业务用户A使用的便是该套计划删除的库,故导出A用户,导入到新环境中,expdp/impdp导入导出中均无报错。昨天在新环境给恢复成功,今天业务反映有报错,在新环境中查看确实没有该function,而老环境中有该function,但是是用户B的,猜测之前老环境是给A建立了B的synonym。
解决方法:
1、获取创建该函数的DDL语句,在新环境中直接创建该function
1
2
3
4
5
6
|
SQL> set long 999 SQL> select dbms_metadata.get_ddl( 'FUNCTION' , 'WM_CONCAT' , 'TBCS' ) from dual; DBMS_METADATA.GET_DDL( 'FUNCTION' , 'WM_CONCAT' , 'TBCS' ) -------------------------------------------------------------------------------- CREATE OR REPLACE EDITIONABLE FUNCTION "TBCS" . "WM_CONCAT" (P1 VARCHAR2) RETURN clob AGGREGATE USING WM_CONCAT_IMPL; |
执行DDL语句
1
2
3
4
|
SQL> CREATE OR REPLACE EDITIONABLE FUNCTION "AOPEN" . "WM_CONCAT" (P1 VARCHAR2) RETURN clob AGGREGATE USING WM_CONCAT_IMPL; 2 / Warning: Function created with compilation errors. SQL> |
此操作后,明显报错了,让业务测试,肯定测不过,查看函数是无效的
1
2
3
4
5
|
SQL> select OWNER,OBJECT_NAME,SUBOBJECT_NAME,OBJECT_TYPE,LAST_DDL_TIME from dba_objects where object_name= upper ( 'wm_concat' ) ; OWNER OBJECT_NAME SUBOBJECT_NAME OBJECT_TYPE LAST_DDL_TIME -------------------- ------------------------------ ------------------------------ ----------------------- --------------- A WM_CONCAT FUNCTION 20191121 172355 SQL> |
2、导出function在导入新环境
由于第一种方法不行,故考虑第二种方法,把老环境B用户的wm_concat函数迁移到新环境,测试可行否
导出function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
expdp \ '/ as sysdba \' directory=expdp_2019 dumpfile=function_wm_concat_20191121.dmp logfile=function_wm_concat_expdp_20191121.log schemas=B include=function:\"IN \'WM_CONCAT\'\" Export: Release 12.1.0.2.0 - Production on Thu Nov 21 17:46:38 2019 Copyright (c) 1982, 2014, Oracle and/or its affiliates. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, Automatic Storage Management, OLAP, Advanced Analytics and Real Application Testing options Starting "SYS"."SYS_EXPORT_SCHEMA_02": "/******** AS SYSDBA" directory=expdp_2019 dumpfile=function_wm_concat_20191121.dmp logfile=function_wm_concat_expdp_20191121.log schemas=B include=function:"IN ' WM_CONCAT' " Estimate in progress using BLOCKS method... Total estimation using BLOCKS method: 0 KB Processing object type SCHEMA_EXPORT/FUNCTION/FUNCTION Processing object type SCHEMA_EXPORT/FUNCTION/ALTER_FUNCTION Master table " SYS "." SYS_EXPORT_SCHEMA_02 " successfully loaded/unloaded ****************************************************************************** Dump file set for SYS.SYS_EXPORT_SCHEMA_02 is: /ora12c/oracle/dir_dump/function_wm_concat_20191121.dmp Job " SYS "." SYS_EXPORT_SCHEMA_02" successfully completed at Thu Nov 21 17:47:27 2019 elapsed 0 00:00:47 |
导入新环境,使用户转换,由B转换为A
1
2
3
4
5
6
7
8
9
10
11
12
|
impdp \'/ as sysdba \' directory=DIR_DUMP dumpfile=function_wm_concat_20191121.dmp logfile=function_wm_concat_impdp_20191121.log remap_schema=B:A Import: Release 12.1.0.2.0 - Production on Thu Nov 21 17:48:53 2019 Copyright (c) 1982, 2014, Oracle and / or its affiliates. All rights reserved. Connected to : Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, Automatic Storage Management, OLAP, Advanced Analytics and Real Application Testing options Master table "SYS" . "SYS_IMPORT_FULL_01" successfully loaded/unloaded Starting "SYS" . "SYS_IMPORT_FULL_01" : "/******** AS SYSDBA" directory=DIR_DUMP dumpfile=function_wm_concat_20191121.dmp logfile=function_wm_concat_impdp_20191121.log remap_schema=B:A Processing object type SCHEMA_EXPORT/ FUNCTION / FUNCTION Processing object type SCHEMA_EXPORT/ FUNCTION /ALTER_FUNCTION ORA-39082: Object type FUNCTION : "AOPEN" . "WM_CONCAT" created with compilation warnings Job "SYS" . "SYS_IMPORT_FULL_01" completed with 1 error(s) at Thu Nov 21 17:49:00 2019 elapsed 0 00:00:05 |
查看函数状态,依旧invalid
1
2
3
4
|
SQL> select owner,object_name,object_type ,status from dba_objects where owner not in ( 'SYS' , 'SYSTEM' ) AND status != 'VALID' ; OWNER OBJECT_NAME OBJECT_TYPE STATUS ------------------------------ ------------------------------ ----------------------- ------- A WM_CONCAT FUNCTION INVALID |
3、手工创建该函数
考虑到第一种方法只是创建了function,而包体等内容并没有创建,故手工创建package、body、function
a、以sys用户创建包、包体、函数
1
2
3
4
5
6
7
8
9
10
11
12
13
|
CREATE OR REPLACE TYPE WM_CONCAT_IMPL AS OBJECT ( CURR_STR VARCHAR2(32767), STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT WM_CONCAT_IMPL) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT WM_CONCAT_IMPL, P1 IN VARCHAR2) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN WM_CONCAT_IMPL, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT WM_CONCAT_IMPL, SCTX2 IN WM_CONCAT_IMPL) RETURN NUMBER ); |
b、创建类型body
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
|
CREATE OR REPLACE TYPE BODY WM_CONCAT_IMPL IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT WM_CONCAT_IMPL) RETURN NUMBER IS BEGIN SCTX := WM_CONCAT_IMPL( NULL ) ; RETURN ODCICONST.SUCCESS; END ; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT WM_CONCAT_IMPL, P1 IN VARCHAR2) RETURN NUMBER IS BEGIN IF(CURR_STR IS NOT NULL ) THEN CURR_STR := CURR_STR || ',' || P1; ELSE CURR_STR := P1; END IF; RETURN ODCICONST.SUCCESS; END ; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN WM_CONCAT_IMPL, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := CURR_STR ; RETURN ODCICONST.SUCCESS; END ; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT WM_CONCAT_IMPL, SCTX2 IN WM_CONCAT_IMPL) RETURN NUMBER IS BEGIN IF(SCTX2.CURR_STR IS NOT NULL ) THEN SELF.CURR_STR := SELF.CURR_STR || ',' || SCTX2.CURR_STR ; END IF; RETURN ODCICONST.SUCCESS; END ; END ; |
c、创建函数
1
|
CREATE OR REPLACE FUNCTION wm_concat(P1 VARCHAR2) RETURN VARCHAR2 AGGREGATE USING WM_CONCAT_IMPL ; |
d、创建同义词并授权
1
2
3
4
|
create public synonym WM_CONCAT_IMPL for sys.WM_CONCAT_IMPL create public synonym wm_concat for sys.wm_concat grant execute on WM_CONCAT_IMPL to public grant execute on wm_concat to public |
然后查看function状态,正常状态。至此问题解决。
总结
1、从网上找资料了解到,11gr2和12C上已经摒弃了wm_concat函数,而应用在程序中确使用了该函数,导致程序出现错误,为了减轻程序员修改程序的工作量,只有通过手工创建个wm_concat函数,来临时解决该问题,但是注意,及时创建了该函数,在使用的过程中,也需要用to_char(wm_concat())方式,才能完全替代之前的应用。
2、也查到了说VMSYS用户下有该函数,但是默认该用户是锁定的,此次问题我也解锁了VMSYS用户,但是并无该function
1
2
3
4
|
SQL> alter user WMSYS account unlock; User altered. SQL> select owner,object_name,object_type from dba_objects where owner= 'WMSYS' and object_type = 'FUNCTION' ; no rows selected |
3、手工重建,保留脚本以后出现类似问题可以很快速重建。