• ORA-22922: nonexistent LOB value


    ORA-22922: nonexistent LOB value

    1 现象及错误信息

    项目现场反馈报表查询系统执行一个查询并导出的功能,无法将查询结果导出,报错:文件太大,不能作为附件。而实际上数据量是很小的。

    同时发来了执行的SQL语句。我连上环境执行,发现报的是ORA-22922错误。错误信息如下:

    oerr ora 22922
    22922, 00000, "nonexistent LOB value"
    //  *Cause:  The LOB value associated with the input locator does not exist.
    //           The information in the locator does not refer to an existing LOB.
    //  *Action: Repopulate the locator by issuing a select statement and retry
    //           the operation.
    

    按照官方的提示信息来看,是在根据一定条件查询LOB时,没有找到LOB对象。 sql 语句由于是涉及到了业务表和逻辑,这里不展示。

    2 分析

    该SQL从一个视图中查询数据。而从视图本身来看是没有LOG对象的。

       select column_name,data_type from dba_tab_cols where owner='REP' AND TABLE_NAME='&view_name';
    
    COLUMN_NAME          DATA_TYPE
    -------------------- --------------------
    CUSTOMER_NAME        VARCHAR2
    CUSTOMER_ID          NUMBER
    CUSTOMER_CODE        VARCHAR2
    INVOICE_NO           VARCHAR2
    BOOK_PAY             NUMBER
    CASH_PAY             NUMBER
    AMOUNT               NUMBER
    PAYMENT_NO           VARCHAR2
    NUM                  NUMBER
    PAY_TYPE             VARCHAR2
    CHG_ITEM_NAME        VARCHAR2
    PAYMENT_DATE         DATE
    ORG_NAME             VARCHAR2
    OP_NAME              VARCHAR2
    ACTION_NAME          VARCHAR2
    OFFICE_ORG_ID        NUMBER
    OPERATOR_ID          NUMBER
    

    继续往下挖,这里面肯定是有LOB对象的。 发现该视图是从另外一张视图里查询的,继续挖, 最后发现一个视图的创建语句如下:

      select .. column_list ...
    from rep.view_sk_1     t
    left join 
    ( select  PAYMENT_NO, to_char(wm_concat(d.invoice_no))    invoice_no
    from .... 
    

    这个视图里有 wm_concat 函数,该函数的返回值是LOB类型。 经测试,将该行注释掉以后,可以正常查询,至此可以肯定, 问题就是由该函数引起的。

    wm_concat 函数是一个列转行的函数,将一列的多行数据转化为一行数据,比如

      salary
    -------
      10000
       9000
       8500
    

    经wm_concat 转换 select wm_concat(salary) from employee where depno=20; 可以转换成

      salary
    -------
    10000,9000,8500
    

    并且以lob类型返回 。 在视图的创建语句中,也发现, 使用了to_char ,看来研发也注意到了这个问题,避免了使用LOB类型。 可是,他们并不知道的是, wm_concat 由于是Lob 类型,是不能进行group by ,distinct 以及union 共存的,因为会偶发ORA-22922错误 。 这里需要注意,是偶发,不是必然。这也算是oracle 的一个小bug吧。

    在Oracle 11G 中,新推出了一个函数有相似的功能是listagg(column_name,'seprator') within group ( order by ..)

    3 解决

    to_char(wm_concat(d.invoice_no)) invoice_no 使用listagg 替换为 LISTAGG(d.invoice_no,',') WITHIN GROUP (ORDER BY PAYMENT_NO) INVOICE_NO 。 经测试,报错不再发生 。替换后的视图创建语句如下:

    select  .. column_list ..
    from rep.view_sk_1     t
    left join
    ( select  PAYMENT_NO, LISTAGG(d.invoice_no,',') WITHIN GROUP (ORDER BY PAYMENT_NO)  invoice_no
    from .....
    

    4 知识总结

    出现这个错误很多时候是使用了wmsys.wm_concat的同时使用了group ,distinct 或者union, 本来两者没有问题,问题在于:

    1. Oracle Database 10g Enterprise Edition Release 10.2.0.5.0以后的版本wmsys.wm_concat查询出的是LOB类型
    2. oralce的SQL语句中若查询了LOB字段是不能使用distinct,union,和group by等关键字的。
    3. 并且在12C 以后,Oracle官方软件不再提供wm_concat函数,因此从兼容性上来看,也不建议使用wm_concat.

    因此,以后在编写PLSQL时,留意一下该问题即可。

    Author: halberd.lee

    Created: 2020-07-01 Wed 21:11

    Validate

  • 相关阅读:
    简单实现抽象工厂模式
    mongodb 最新版安装和配置(单机版)
    排序的三个基础算法 (python实现)
    关于学习,关于工具
    嵌入式linux教程
    用软件工程分析开源项目octave的移植
    C++高质量编程笔记
    从高级软件工程角度分析毕业设计项目存在的问题
    史话未完待续。。。
    乔治布尔
  • 原文地址:https://www.cnblogs.com/halberd-lee/p/13221548.html
Copyright © 2020-2023  润新知