一客户让我看下一个expdp的导出错误,信息如下(表名已处理):
ora-31693 :table data object xx.xxxx failed to load/unload and is being skipped due to error;
ora-29913 :error in executing ODCIEXTTABLEPOPULATE callout
ora-22923 :amount of data specified in streaming LOB write is 0
用oerr ora 22923 在操作系统上看了下oracle给的建议:
意思是不能朝lob字段里面写入零字节,该表上有个long raw类型的字段,这个已经被oracle淘汰的字段总是让人烦恼。
现在我怀疑该字段中可能存在空值的情况,但long raw字段又不支持谓词where的查询,所以无法定位到哪条记录存在空值。。。(也许这个可以作为切入点,来定位是否是空值,然而进一步删除该空值的情况)
在metalink上找了半天,也没有找到符合错误描述的文档,有点无奈。更多看到的都是建议将long换成lob型,但客户这边的这套系统是基于8i开发的,历史遗留问题总是难以解决的。
现在客户想要清理这张带有long raw字段表的部分数据,数据量很大,想利用expdp/impdp的方式来做,但总是报出如上错误,我这边又找不到好的方法,也不能确认是不是某个未公开的bug,只好像metalink所说的那样,建议选用exp/imp的方式来做了。客户勉强能接受,但对速度方面,还是有很多顾虑 。
倒是头一次遇到这样的情况,情绪有点低落啊,毕竟问题没有圆满解决。客户这边又因为牵一发而动全身的缘故,不能改动表结构。
我再找找看,以期获得某意外之喜,或某些灵感。
------------------------------------------------------------------------2015-03-31 续,问题不解决,寝食难安啊-------------------------------------------------------------------------
之前一直陷入了如何解决这个ora问题的思路陷阱里面,突然意识的,我完全可以跳过该ora错误,既然oracle expdp不支持0字节的lob导出,那么我就找出那条0字节的数据,在metalink上找了查找long raw字段大小的方法,贴在下面:
create or replace function lr_length( p_rowid in rowid ) return
number
as
l_raw long raw;
begin
select name into l_raw
from expdptest
where rowid = p_rowid;
if ( l_raw is null ) then
return null;
else
return utl_raw.length(l_raw);
end if;
exception
when others then return NULL;
end;
/
select rowid, lr_length( rowid ) len from expdptest ;
后来执行结果验证了我先前的猜测,果然存在一条long raw类型字段值为null的情况,和业务商量,建议在expdp的时候跳过该值,expdp导出成功。