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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM