xzh2000的博客 本人提供杭州地区Oracle现场技术支持服务,包括性能调整、DataGuard、RAC等。
23 07, 2008
如何计算long字段的长度
作者 xzh2000 16:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

有一个应用,在访问clob时抛出异常如下:

FATAL ERROR IN TWO-TASK SERVER: error = 12152
*** 2008-07-17 18:28:43.912
ksedmp: internal or fatal error
ORA-12571: TNS:packet writer failure

RDBMS:9206,查metalink,证实为一个未公开的bug,为了挠过该bug,将clob类型的字段改成long类型,结果访问还是有问题,当长度超过一定的长度时,proc程序就只能读取前4000个字符,因为应用已经发布,修改代码已经来不急。查看了一下long字段的内容,发现文字内容很少的,大部分都是html的格式代码,只需要找出长度超过4000的记录,去掉该部分html代码应用就可以恢复正常;但怎么在long字段中找到超过4000字符记录呢?


用length、dbms_lob.getlength都不适合long类型,只好通过一段pl/sql代码,来计算超过4k的记录:

declare
v_str clob;
v_cnt number;
v_id number;
begin
for i in (select * from test order by id) loop
v_str := i.txt;
v_cnt := dbms_lob.getlength(v_str);

if v_cnt > 4000 then
dbms_output.put_line('ID='||i.id||' LENGTH:'||dbms_lob.getlength(v_str));
end if;
end loop;
end;

查metalink,如何计算long字段的长度,找到官方推荐的方式,与偶计算结果的有一定的差异,但也可以达到自己的要求:

CREATE OR REPLACE FUNCTION l_length(cTabName varchar2,
cColName varchar2,
cRowid varchar2) RETURN NUMBER IS
cur_id integer;
buff varchar2(32767);
len integer;
offset integer;
v_length integer;
stmt varchar2(500);
ret integer;
BEGIN

stmt := ' SELECT ' || cColName || ' FROM ' || cTabName ||
' WHERE rowid = ' || '''' || cRowid || '''';

cur_id := dbms_sql.open_cursor;
dbms_sql.parse(cur_id, stmt, dbms_sql.NATIVE);
dbms_sql.define_column_long(cur_id, 1);
ret := dbms_sql.execute(cur_id);

IF (dbms_sql.fetch_rows(cur_id) > 0) THEN
offset := 0;
len := 0;
LOOP
dbms_sql.column_value_long(cur_id, 1, 32767, offset, buff, v_length);
len := len + v_length;
EXIT WHEN v_length < 32767;
offset := offset + v_length;
END LOOP;
END IF;
dbms_sql.close_cursor(cur_id);
return(len);
END;

----

set serveroutput on size 100000;

DECLARE
len number;
cRowid varchar2(30);
num number;
cursor T_CURSOR is
SELECT rowid
FROM TABLE_NAME;
BEGIN
open T_CURSOR;
LOOP
FETCH T_CURSOR
INTO cRowid;
EXIT WHEN T_CURSOR%NOTFOUND;
len := l_length('TABLE_NAME', 'LONG_COLUMN_NAME', cRowid);
dbms_output.put_line(rowidtochar(cRowid) || '' ||
to_char(len, '999999'));
END LOOP;
END;
/

Comments
博客日历
« 七月 2009 »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
搜索
最新发表
文章分类
文章归档
网站链接
新闻聚合