我们在使用oracle时会面对各种类型的字段,有时需要不同字段类型的转换,比如blob转char
常规替换
函数解析:
Utl_Raw.CAST_TO_RAW (blob字段) : 将blob字段转为字符串
REPLACE(string, str, tgt) : 替换函数, string中的str 替换成tgt
Utl_Raw.CAST_TO_RAW(string) : 将字符串转为raw类型
UPDATE 表 a
SET a.blob字段 = Utl_Raw.CAST_TO_RAW ( REPLACE ( Utl_Raw.Cast_To_Varchar2 ( a.blob字段 ), '目标字段', '要替换成的字段' ) )
WHERE 条件
Blob大数据替换
用上述方法BLOB数据过多时会出现以下报错:
ORA-22835: 缓冲区对于 CLOB 到 CHAR 转换或 BLOB 到 RAW 转换而言太小 (实际: 3744, 最大: 2000)
to_char方法将clob类型转换成varchar类型出了问题,oracle中varchar最大的长度是4000。把clob大文本类型直接转换成varcahr类型时,如果clob的长度小于4000,没有超过varchar的最大值,不会出问题,一旦超过4000就会报错
这时候就需要使用函数将blob转为varchar2
上述内容及转化方法参数:oracle修改Blob类型数据,批量更新数据做字符替换_oracle blob转字符串_Tine.的博客-CSDN博客
到这里你以为问题就解决了嘛!当然没有,大佬的csdn中提到的两个函数C2B和Blob_To_Varchar以及存储过程更新多数据的方法可以解决大多数的问题。但是由于blob字段在oracle中的最大长度是2G,所以一条blob字段的数据可以超级大超级大。
当blob字段中的数据达到32767个字符以上,上述的方法就会变得无效,你执行sql或存储过程后依旧会报:缓冲区对于 CLOB 到 CHAR 转换或 BLOB 到 RAW 转换而言太小
而我的客户给我展示的生产环境最大一条数据的字符数是140万多,在我两天不断的搜索和与做数据开发方面同事的研究下,得到了一个朴实无华且真实有效的方法。
首先,在原解决方法的基础上修改函数Blob_To_Varchar
-- clob转成varchar2的方法
CREATE OR REPLACE FUNCTION Blob_To_Varchar ( Blob_In IN Blob ) Return clob IS V_Varchar VARCHAR2 ( 32767 );
V_Varchar1 VARCHAR2 ( 32767 );
V_Start Pls_Integer := 1;
V_Buffer Pls_Integer := 32767;
BEGIN
IF Dbms_Lob.Getlength ( Blob_In ) IS NULL
THEN Return '';
END IF;
V_Varchar1 := '';
--return to_char(Ceil(Dbms_Lob.Getlength(Blob_In) / V_Buffer));
--当转换出来的字符串乱码时,可尝试用注释掉的函数
--V_Varchar := Utl_Raw.Cast_To_Varchar2(Utl_Raw.Convert(Dbms_Lob.Substr(Blob_In, V_Buffer, V_Start),'SIMPLIFIED CHINESE_CHINA.ZHS16GBK', 'AMERICAN_THE NETHERLANDS.UTF8'));
V_Varchar := Utl_Raw.Cast_To_Varchar2 ( Dbms_Lob.Substr( Blob_In, V_Buffer, V_Start ) );
V_Varchar1 := V_Varchar1 || V_Varchar;
Return V_Varchar1;
END Blob_To_Varchar;
原函数中的V_Buffer Pls_Integer是substr截取字符串的长度,通过循环截取每次截取4000长度的字符在将其转为Varchar2类型就是原函数的作用。
对函数的修改为将截取长度改为Varchar2字段的最大长度,并将循环移除,使函数每次固定截取转化32767的字符。
(当字段长度超过32767的时候,循环截取在第九次时会报错缓冲区不够等问题,报错语句是V_Varchar1 := V_Varchar1 || V_Varchar;)
如果你也是上面的报错,恭喜你我们错的都一样
当然朴实无华的方法就是编写多个函数分别的超长字段多个部分进行截取,在将他们拼接起来
update ceshi t
set content = (C2B(to_clob((SELECT REPLACE(Blob_To_Varchar1(content),
'2.2.2.2','1.1.1.1')
from ceshi a
where a.infoid = t.infoid)||
(SELECT REPLACE(Blob_To_Varchar2(content),
'2.2.2.2','1.1.1.1')
from ceshi a
where a.infoid = t.infoid)
)))
where length(content) >32767
用这个方法你可以无限套娃,进行blob字段中超长字符的转化。
希望对你有所帮助!