How to call REPLACE with CLOB (without exceeding 32K)
oracle, oracle11gr2, plsql
Solution
Here is a rough first draft for a function that will do the job with certain limitations, it hasn't been very well tested yet:
function replace_with_clob
(i_source in clob
,i_search in varchar2
,i_replace in clob
) return clob is
l_pos pls_integer;
begin
l_pos := instr(i_source, i_search);
if l_pos > 0 then
return substr(i_source, 1, l_pos-1)
|| i_replace
|| substr(i_source, l_pos+length(i_search));
end if;
return i_source;
end replace_with_clob;
It only does a single replace on the first instance of the search term.
declare
v2 varchar2(32767);
cl_small clob;
cl_big clob;
cl_big2 clob;
begin
v2 := rpad('x', 32767, 'x');
dbms_output.put_line('v2:' || length(v2));
cl_small := v2;
dbms_output.put_line('cl_small:' || length(cl_small));
cl_big := v2 || 'y' || v2;
dbms_output.put_line('cl_big[1]:' || length(cl_big));
cl_big2 := replace(cl_big, 'y', cl_small);
dbms_output.put_line('cl_big[2]:' || length(cl_big2));
cl_big2 := replace_with_clob(cl_big, 'y', cl_big);
dbms_output.put_line('cl_big[3]:' || length(cl_big2));
end;
/
v2:32767
cl_small:32767
cl_big[1]:65535
cl_big[2]:98301
cl_big[3]:131069
Problem
Oracle 11g has certainly improved usability of CLOBs, having overloaded most of the string functions so they now work natively with CLOBs. However, a colleague was getting this error from his code: ``` ORA-22828: input pattern or replacement parameters exceed 32K size limit 22828. 00000 - "input pattern or replacement parameters exceed 32K size limit" *Cause: Value provided for the pattern or replacement string in the form of VARCHAR2 or CLOB for LOB SQL functions exceeded the 32K size limit. *Action: Use a shorter pattern or process a long pattern string in multiple passes. ``` This only occurred when the third parameter to `replace` was a CLOB with more than 32k characters. (Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production) Test case: ``` declare v2 varchar2(32767); cl_small clob; cl_big clob; cl_big2 clob; begin v2 := rpad('x', 32767, 'x'); dbms_output.put_line('v2:' || length(v2)); cl_small := v2; dbms_output.put_line('cl_small:' || length(cl_small)); cl_big := v2 || 'y' || v2; dbms_output.put_line('cl_big[1]:' || length(cl_big)); cl_big2 := replace(cl_big, 'y', cl_small); dbms_output.put_line('cl_big[2]:' || length(cl_big2)); cl_big2 := replace(cl_big, 'y', cl_big); dbms_output.put_line('cl_big[3]:' || length(cl_big2)); end; / ``` Results: ``` v2:32767 cl_small:32767 cl_big[1]:65535 cl_big[2]:98301 ORA-22828: input pattern or replacement parameters exceed 32K size limit ``` This seems at odds with the docs which imply that the replacement string may be a CLOB - I would have thought this should imply that any CLOB would be allowed, not just those that happen to be <32K: http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions153.htm#SQLRF00697