oracle11g ora 00904,【排故篇_oracle11g升19c之ORA-00904 WM_CONCAT invalid identifie排故

【引言】

个人公众号之前的一篇文章曾经介绍过无效对象的问题。介绍到在数据库日常运维中,数据库中一些对象(如:Package、Procedure、Function、View、同义词等会失效,状态为INVALID,需定期检查数据库中存在哪些失效对象。自动失效的对象,一般会在下次调用的时候,会被重新编译,所以一般也不需要人工干预。对于存在异常的对象则需要手动重新编译;一个场景就是数据迁移也会导致无效对象的产生。

**

《Oracle番:啥是无效对象,出现时如何破?》

**

最近的一次oracle库大版本升级,版本从11g升级至19c;按照《Oracle番:啥是无效对象,出现时如何破?》,升级至19c后,执行如下utlrp.sql脚本编译了数据库失效对象后,还是有个应用账号报无效对象编辑失效的现象。

sql>@$ORACLE_HOME/rdbms/admin/utlrp.sql

报错信息如下:

ORA-00904: “WM_CONCAT”: invalid identifie

经了解,wm_contact(column)函数从oracle10g开始使用,然而12C以上版本摒弃了wm_concat函数,导致不能识别"WM_CONCAT"函数。大家都知道,WM_CONCAT"可以实现oracle中字段的合并,wm_concat(列名)函数,能把指定的列的值,按照group by 中指定的分隔方法,用逗号拼接起来。通常用法如下例:

#通用用法

select id,wm_concat(test) result

from test

group by id;

#使用时记得用to_char()封装下

select id,to_char(wm_concat(test)) result

from test

group by id;

注意:

实际使用中,需用to_char(wm_concat())方式封装,方可正常调用。

至于为何oracle在12c的版本中抛弃不用wm_contact(column)?

个人这里大致推测下:应该和函数执行效率低有关,因为用过的朋友有切身体会,万行的查询合并,执行时间较长。另,wm_contact英文描述为undocumented,意味着随时可能发生变更;10.2.0.5上,其返回类型从varchar2变为了clob,12c后续版本,直接就取消了此函数。用到此函数的数据库发生大版本升级,如本人的11g升级19c,就是一大坑,因升级后如不注意,应用在进行功能性测试时,肯定出问题。

后续作者将继续研究下,也欢迎大家留言讨论oracle弃用wm_contact的原因。

本次升级,11g中版本对应的应用程序中使用了wm_contact该函数,升级后的19c没有此wmsys.wm_contact函数,故致使所以来的view和package报错,出现如下:

ORA-00904: “WM_CONCAT”: invalid identifie

**

问题如何解决?**

解决方案有三种:

方法1:19c中创建低版本的wm_contact函数;

方法2:19c中手动创建wm_contact函数;

方法3:使用其替代函数,listagg

方法1创建wm_contact函数

从原有低版本11g中copy相应的文件,在19c中执行创建wm_contact函数;具体如下:

从11g的ORACLE_HOME/rdbms/admin目录下拷贝owmctab.plb、owmaggrs.plb、owmaggrb.plb三个文件至19c的ORACLE_HOME/rdbms/admin/目录下。然后依次执行owmctab.plb、owmaggrs.plb、owmaggrb.plb这三个文件。

查看owmctab.plb脚本内容,因owmctab.plb需要引用owmt9012.plb,而owmt9012.plb需要引用owmt9013.plb,故需要需要从11g中scp到19C中,如下共计5个文件。

owmctab.plb

owmt9013.plb

owmt9012.plb

owmaggrs.plb

owmaggrb.plb

19c中oracle环境下依次执行如下命令:

SQL> @?/rdbms/admin/owmctab.plb

SQL> @?/rdbms/admin/owmaggrs.plb

SQL> @?/rdbms/admin/owmaggrb.plb

方法2:19c中手动创建wm_contact函数

参考如下链接:

https://blog.csdn.net/alicewang99/article/details/89945252

**

创建wm_concat函数**

–首先使用dba账号登录oracle数据库

–解锁wmsys用户

alter user wmsys account unlock;

–并为wmsys用户授权,可根据需要授权,不建议授权所有权限

grant all privileges to wmsys;

–如果不知道wmsys用户的密码,可以修改其密码

alter user wmsys identified by 123456;

–使用wmsys用户登录数据库

conn wmsys/123456

–在wmsys下创建可用的wm_concat函数,直接执行以下语句

–定义类型

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

);

/

–定义类型body:

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;

/

–自定义行变列函数:

CREATE OR REPLACE FUNCTION wm_concat(P1 VARCHAR2)

RETURN VARCHAR2 AGGREGATE USING WM_CONCAT_IMPL ;

/

–创建完成,给其创建同义词及授权,以供其他用户能正常使用。

create public synonym WM_CONCAT_IMPL for wmsys.WM_CONCAT_IMPL

/

create public synonym wm_concat for wmsys.wm_concat

/

grant execute on WM_CONCAT_IMPL to public

/

grant execute on wm_concat to public

/

方法3:使用替代函数listagg

参考链接:

https://blog.csdn.net/sinat_36257389/article/details/81004843

使用listagg函数代替

基本语法:

SELECT

T .DEPTNO,

listagg (T.ENAME, ‘,’) WITHIN GROUP (ORDER BY T.ENAME) names

FROM

SCOTT.EMP T

WHERE

T.DEPTNO = ‘20’

GROUP BY

T.DEPTNO

本文采用了方法1。

【结语】

1.个人进行oracle11g升级12c以上大版本的升级案例中,所遇到的第一个大坑;各位亲,请留意。

2.至于oracle官方为何弃用wm_contact函数,文中个人初步推断为该函数执行效率低的原因,后续具体原因,文章待定。

3.Oracle大版本后的升级,一定要谨慎再谨慎,充分做好应用测试。

【参考】

https://www.cnblogs.com/YuyuanNo1/p/7910714.html

【参考】

https://blog.csdn.net/sinat_36257389/article/details/81004843

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值