如何根据 CLOB 的大小将 CLOB 转换为 NVARCHAR2 块?

How to convert CLOB into NVARCHAR2 chunks as per the size of the CLOB?

我们有一个生成 HTML 报告并将整个值存储到 CLOB 字段中的过程。然后它被发送到另一个程序,该程序使用 UTL_SMTP 发送电子邮件。电子邮件大小可能会有所不同,通常是一个巨大的大小。

我正在将 CLOB 值转换为 VARCHAR2 块,并通过多个变量将不同的块传递给 UTL_STMP。

   chunk1            varchar2 (4000);
   chunk2            varchar2 (4000);
   chunk3            varchar2 (4000);
   chunk4            varchar2 (4000);
   chunk5            varchar2 (4000);
   chunk6            varchar2 (4000);
   chunk7            varchar2 (4000);
   chunk8            varchar2 (4000);
   chunk9            varchar2 (4000);
   chunk10           varchar2 (4000);
   chunk11           varchar2 (4000);

将 CLOB 转换成不同的块并存储在不同的变量中:

   chunk1 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 1);
   chunk2 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 4001);
   chunk3 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 8001);
   chunk4 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 12001);
   chunk5 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 16001);
   chunk6 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 20001);
   chunk7 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 24001);
   chunk8 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 28001);
   chunk9 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 32001);
   chunk10 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 36001);
   chunk11 := DBMS_LOB.SUBSTR (EM_TEXT, 4000, 40001);

然后将变量传递给UTL_SMTP:

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk1))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk2))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk3))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk4))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk5))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk6))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk7))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk8))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk9))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk10))
   );

   UTL_SMTP.WRITE_RAW_DATA (
      M_MAIL_CONN,
      UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (UTL_RAW.CAST_TO_RAW (chunk11))
   );

截至今天,11 个变量就足够了,但明天可能会增加。如果变量多于 CLOB 数据,过程将抛出错误。

我需要找到一种方法将 CLOB 动态分配给不同的变量,然后只将带有数据的变量传递给 UTL_SMTP。

提前感谢您提供提示、建议和示例。

我使用了 的答案并进行了如下修改,得到了我想要的结果。

DECLARE
   TYPE typ_comment IS TABLE OF varchar2 (4000);
   v_varchar         typ_comment := typ_comment ();
   v_clob            CLOB;
   k                 number;
   j                 number := 4000;

BEGIN
  SELECT   EM_TEXT INTO v_clob FROM DUAL; 

   k := CEIL (DBMS_LOB.getlength (v_clob) / j);
   v_varchar.EXTEND (k);

   FOR i IN 1 .. k
   LOOP
      v_varchar (i) := DBMS_LOB.SUBSTR (v_clob, j, 1 + j * (i - 1));

      UTL_SMTP.WRITE_RAW_DATA (
         M_MAIL_CONN,
         UTL_ENCODE.QUOTED_PRINTABLE_ENCODE (
            UTL_RAW.CAST_TO_RAW (v_varchar (i))
         )
      );
   END LOOP;
END;