如何获取 Oracle 中 CLOB 列的大小(以字节为单位)?

发布于 2024-08-12 05:56:09 字数 177 浏览 10 评论 0原文

如何获取 Oracle 中 CLOB 列的大小(以字节为单位)?

LENGTH()DBMS_LOB.getLength() 都返回 CLOB 中使用的字符数,但我需要知道使用了多少字节(我正在处理多字节字符集)。

How do I get the size in bytes of a CLOB column in Oracle?

LENGTH() and DBMS_LOB.getLength() both return number of characters used in the CLOB but I need to know how many bytes are used (I'm dealing with multibyte charactersets).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

羁绊已千年 2024-08-19 05:56:09

经过一番思考,我想出了这个解决方案:

 LENGTHB(TO_CHAR(SUBSTR(<CLOB-Column>,1,4000)))

SUBSTR 仅返回前 4000 个字符(最大字符串大小)

TO_CHARCLOB 转换为 VARCHAR2

LENGTHB 返回字符串使用的长度(以字节为单位)。

After some thinking i came up with this solution:

 LENGTHB(TO_CHAR(SUBSTR(<CLOB-Column>,1,4000)))

SUBSTR returns only the first 4000 characters (max string size)

TO_CHAR converts from CLOB to VARCHAR2

LENGTHB returns the length in Bytes used by the string.

木落 2024-08-19 05:56:09

我将我的评论添加为答案,因为它解决了比接受的答案更广泛的情况下的原始问题。注意:您仍然必须知道数据的最大长度和多字节字符的大致比例。

如果 CLOB 大于 4000 字节,则需要使用 DBMS_LOB.SUBSTR 而不是 SUBSTR。 请注意,金额偏移参数在DBMS_LOB.SUBSTR中是相反的。

接下来,您可能需要对小于4000的金额进行子字符串化,因为这参数是字符数,如果你有多字节字符,那么4000个字符将超过4000字节长,你会得到ORA- 06502:PL/SQL:数字或值错误:字符串缓冲区太小,因为子字符串结果需要适合 VARCHAR2,该 VARCHAR2 具有 4000 字节的限制。您可以检索的确切字符数取决于数据中每个字符的平均字节数。

所以我的答案是:

LENGTHB(TO_CHAR(DBMS_LOB.SUBSTR(<CLOB-Column>,3000,1)))
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,3000,3001))),0)
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,6000,6001))),0)
+...

您可以根据需要添加尽可能多的块来覆盖最长的 CLOB,并根据数据的平均每个字符字节调整块大小。

I'm adding my comment as an answer because it solves the original problem for a wider range of cases than the accepted answer. Note: you must still know the maximum length and the approximate proportion of multi-byte characters that your data will have.

If you have a CLOB greater than 4000 bytes, you need to use DBMS_LOB.SUBSTR rather than SUBSTR. Note that the amount and offset parameters are reversed in DBMS_LOB.SUBSTR.

Next, you may need to substring an amount less than 4000, because this parameter is the number of characters, and if you have multi-byte characters then 4000 characters will be more than 4000 bytes long, and you'll get ORA-06502: PL/SQL: numeric or value error: character string buffer too small because the substring result needs to fit in a VARCHAR2 which has a 4000 byte limit. Exactly how many characters you can retrieve depends on the average number of bytes per character in your data.

So my answer is:

LENGTHB(TO_CHAR(DBMS_LOB.SUBSTR(<CLOB-Column>,3000,1)))
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,3000,3001))),0)
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,6000,6001))),0)
+...

where you add as many chunks as you need to cover your longest CLOB, and adjust the chunk size according to average bytes-per-character of your data.

深爱不及久伴 2024-08-19 05:56:09

对于大于 VARCHAR2 的 CLOB 大小,请尝试此操作:

我们必须将 CLOB 拆分为“VARCHAR2 兼容”大小的部分,对 CLOB 数据的每个部分运行 lengthb,并汇总所有结果。

declare
   my_sum int;
begin
   for x in ( select COLUMN, ceil(DBMS_LOB.getlength(COLUMN) / 2000) steps from TABLE ) 
   loop
       my_sum := 0;
       for y in 1 .. x.steps
       loop
          my_sum := my_sum + lengthb(dbms_lob.substr( x.COLUMN, 2000, (y-1)*2000+1 ));
          -- some additional output
          dbms_output.put_line('step:' || y );
          dbms_output.put_line('char length:' || DBMS_LOB.getlength(dbms_lob.substr( x.COLUMN, 2000 , (y-1)*2000+1 )));
          dbms_output.put_line('byte length:' || lengthb(dbms_lob.substr( x.COLUMN, 2000, (y-1)*2000+1 )));
          continue;
        end loop;
        dbms_output.put_line('char summary:' || DBMS_LOB.getlength(x.COLUMN));
        dbms_output.put_line('byte summary:' || my_sum);
        continue;
    end loop;
end;
/

Try this one for CLOB sizes bigger than VARCHAR2:

We have to split the CLOB in parts of "VARCHAR2 compatible" sizes, run lengthb through every part of the CLOB data, and summarize all results.

declare
   my_sum int;
begin
   for x in ( select COLUMN, ceil(DBMS_LOB.getlength(COLUMN) / 2000) steps from TABLE ) 
   loop
       my_sum := 0;
       for y in 1 .. x.steps
       loop
          my_sum := my_sum + lengthb(dbms_lob.substr( x.COLUMN, 2000, (y-1)*2000+1 ));
          -- some additional output
          dbms_output.put_line('step:' || y );
          dbms_output.put_line('char length:' || DBMS_LOB.getlength(dbms_lob.substr( x.COLUMN, 2000 , (y-1)*2000+1 )));
          dbms_output.put_line('byte length:' || lengthb(dbms_lob.substr( x.COLUMN, 2000, (y-1)*2000+1 )));
          continue;
        end loop;
        dbms_output.put_line('char summary:' || DBMS_LOB.getlength(x.COLUMN));
        dbms_output.put_line('byte summary:' || my_sum);
        continue;
    end loop;
end;
/
野の 2024-08-19 05:56:09

简单的解决方案是将 CLOB 转换为 BLOB,然后请求 BLOB 的长度!

问题是Oracle没有将CLOB转换为BLOB的函数,但我们可以简单地定义一个函数来执行此操作

create or replace
FUNCTION clob2blob (p_in clob) RETURN blob IS 
    v_blob        blob;
    v_desc_offset PLS_INTEGER := 1;
    v_src_offset  PLS_INTEGER := 1;
    v_lang        PLS_INTEGER := 0;
    v_warning     PLS_INTEGER := 0;  
BEGIN
    dbms_lob.createtemporary(v_blob,TRUE);
    dbms_lob.converttoblob
        ( v_blob
        , p_in
        , dbms_lob.getlength(p_in)
        , v_desc_offset
        , v_src_offset
        , dbms_lob.default_csid
        , v_lang
        , v_warning
        );
    RETURN v_blob;
END;

用于获取字节数的SQL命令是

SELECT length(clob2blob(fieldname)) as nr_bytes 

或者

SELECT dbms_lob.getlength(clob2blob(fieldname)) as nr_bytes

我已经在Oracle 10g上测试了这个而不使用Unicode( UTF-8)。
但我认为这个解决方案使用 Unicode(UTF-8) Oracle 实例必须是正确的:-)

我想要渲染,感谢 Nashev,他发布了一个将 clob 转换为 blob 的解决方案 如何在 Oracle 中将 CLOB 转换为 BLOB? 以及这篇用德语编写的文章(代码为 PL/SQL)13ter.info.blog 还提供了将 blob 转换为 clob 的功能!

有人可以测试 Unicode(UTF-8) CLOB 中的 2 个命令,以便我确定这适用于 Unicode 吗?

The simple solution is to cast CLOB to BLOB and then request length of BLOB !

The problem is that Oracle doesn't have a function that cast CLOB to BLOB, but we can simply define a function to do that

create or replace
FUNCTION clob2blob (p_in clob) RETURN blob IS 
    v_blob        blob;
    v_desc_offset PLS_INTEGER := 1;
    v_src_offset  PLS_INTEGER := 1;
    v_lang        PLS_INTEGER := 0;
    v_warning     PLS_INTEGER := 0;  
BEGIN
    dbms_lob.createtemporary(v_blob,TRUE);
    dbms_lob.converttoblob
        ( v_blob
        , p_in
        , dbms_lob.getlength(p_in)
        , v_desc_offset
        , v_src_offset
        , dbms_lob.default_csid
        , v_lang
        , v_warning
        );
    RETURN v_blob;
END;

The SQL command to use to obtain number of bytes is

SELECT length(clob2blob(fieldname)) as nr_bytes 

or

SELECT dbms_lob.getlength(clob2blob(fieldname)) as nr_bytes

I have tested this on Oracle 10g without using Unicode(UTF-8).
But I think that this solution must be correct using Unicode(UTF-8) Oracle instance :-)

I want render thanks to Nashev that has posted a solution to convert clob to blob How convert CLOB to BLOB in Oracle? and to this post written in german (the code is in PL/SQL) 13ter.info.blog that give additionally a function to convert blob to clob !

Can somebody test the 2 commands in Unicode(UTF-8) CLOB so I'm sure that this works with Unicode ?

最笨的告白 2024-08-19 05:56:09

NVL(length(clob_col_name),0) 对我有用。

NVL(length(clob_col_name),0) works for me.

山色无中 2024-08-19 05:56:09

使用表名从 dba_lobs 检查 LOB 段名称。

select TABLE_NAME,OWNER,COLUMN_NAME,SEGMENT_NAME from dba_lobs where TABLE_NAME='<<TABLE NAME>>';

现在使用段名称查找 dba_segments 中使用的字节。

select s.segment_name, s.partition_name, bytes/1048576 "Size (MB)"
from dba_segments s, dba_lobs l
where s.segment_name = l.segment_name
and s.owner = '<< OWNER >> ' order by s.segment_name, s.partition_name;

Check the LOB segment name from dba_lobs using the table name.

select TABLE_NAME,OWNER,COLUMN_NAME,SEGMENT_NAME from dba_lobs where TABLE_NAME='<<TABLE NAME>>';

Now use the segment name to find the bytes used in dba_segments.

select s.segment_name, s.partition_name, bytes/1048576 "Size (MB)"
from dba_segments s, dba_lobs l
where s.segment_name = l.segment_name
and s.owner = '<< OWNER >> ' order by s.segment_name, s.partition_name;
岁月染过的梦 2024-08-19 05:56:09

它只能工作到 4000 字节,如果 clob 大于 4000 字节,那么我们使用这个

declare
v_clob_size clob;

begin

      v_clob_size:= (DBMS_LOB.getlength(v_clob)) / 1024 / 1024;
      DBMS_OUTPUT.put_line('CLOB Size   ' || v_clob_size);   
end;

select (DBMS_LOB.getlength(your_column_name))/1024/1024 from your_table

It only works till 4000 byte, What if the clob is bigger than 4000 bytes then we use this

declare
v_clob_size clob;

begin

      v_clob_size:= (DBMS_LOB.getlength(v_clob)) / 1024 / 1024;
      DBMS_OUTPUT.put_line('CLOB Size   ' || v_clob_size);   
end;

or

select (DBMS_LOB.getlength(your_column_name))/1024/1024 from your_table
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文