Home > Back-end >  Alternate of Varchar2?
Alternate of Varchar2?

Time:06-28

I am getting data in Refcursor and binding in HTML table using for loop to send an email. When I am executive my procedure then it is giving me error of "numeric or value error: character string buffer too small". I have tried CLOB but still not get any success.

Error :-

ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "XXCOMM.XX_EMS_MAIL_PRC_MAINTENANCE", line 113
ORA-06512: at line 6

Below id my procedure in which I am trying to send email.

create or replace PROCEDURE XX_EMS_MAIL_PRC_maintenance
(
  p_site_id  IN  VARCHAR2
)

AS
 
 l_in_date VARCHAR2(200) := NULL;
 
 CURSOR cur_maintenance_list (p_site_id VARCHAR2)
    IS 
      SELECT
            c.instrument_no "Instrument_Number",
            d.instrument_name "Instrument_Name",
            d.eqp_srl_no "EQP_Serial_Number",
            d.ownership "Ownership",
            d.mfg_name "Mfg_Name",
            d.model_no "Model_Number",
            b.plan "Plan",
            a.detail "Plan_Detail",
            c.activity_id "Activity_Id",
            c.maintenance_date "Maintenance_Date",
            c.maintenance_due_date "Maintenance_Due_Date"
            
        FROM
            activity_detail        a,
            activity_master        b,
            maintenance_schedule   c,
            instrument_master      d,
            emp_master             m
        WHERE
            a.plan_id = b.plan_id
            AND d.instrument_no = c.instrument_no
            AND c.plan_id = b.plan_id
            AND c.activity_id = a.activity_id
            AND ( c.instrument_no,
                  c.plan_id,
                  c.activity_id,
                  c.maintenance_due_date ) = (
                SELECT
                    e.instrument_no,
                    e.plan_id,
                    e.activity_id,
                    MAX(e.maintenance_due_date)
                FROM
                    maintenance_schedule e
                WHERE
                    c.plan_id = e.plan_id
                    AND c.instrument_no = e.instrument_no
                    AND c.activity_id = e.activity_id
                GROUP BY
                    e.instrument_no,
                    e.plan_id,
                    e.activity_id
            )
            AND trunc(c.maintenance_due_date) BETWEEN to_date('01-JUL-2022', 'DD-MON-RRRR') AND to_date('01-JUL-2022', 'DD-MON-RRRR')
            AND d.p_manitenance_req <> 'N'
            AND ( m.emp_initial = d.prepared_by
                  OR to_char(m.emp_no) = d.prepared_by )
            AND ( b.site_id = d.site_id
                  OR d.site_id = '001' );
         

  p_to               sys_refcursor; 
  p_cc               sys_refcursor; 
  p_bcc              sys_refcursor; 
  
  v_html_msg             VARCHAR2(32672) := NULL;
      --v_txt_msg varchar2(250) := 'WelCome ....'||chr(10)||'this is a test mail';
  v_to                   VARCHAR2 (1000) := NULL;
  v_cc                   VARCHAR2 (1000) := NULL;
  v_bcc                  VARCHAR2 (2000) := NULL;
  v_from                 VARCHAR2 (150)  := 'abc.com';
    
  v_db_name varchar2(25) := null;

BEGIN  

BEGIN

    v_db_name := null;  
  
  SELECT listagg(EMAIL, ',') WITHIN GROUP (order by Email) INTO v_to FROM sml.xx_lsp_email_master WHERE email_type = 'TO' AND function_name = 'EMS_App_maintenance' AND isactive='Y';

  SELECT listagg(EMAIL, ',') WITHIN GROUP (order by Email) INTO v_cc FROM sml.xx_lsp_email_master WHERE email_type = 'CC' AND function_name = 'EMS_App_maintenance' AND isactive='Y';

--SELECT listagg(EMAIL, ',') WITHIN GROUP (order by Email) INTO v_bcc FROM sml.xx_lsp_email_master WHERE email_type = 'BCC' AND function_name = 'EMS_App';
 
 v_html_msg :='<html><head></head><body><p>Dear All,<br/><br/>
  Please find the details of Maintenance due list for this week in Equipment Management System</p><br/>
  
  
            
  <table border=1>
  <tr>
  <th> I/S Number </th>
  <th> Instrument Name </th>
  <th> EQP Serial Number </th>
  <th> Ownership </th>
  <th> Make </th>
  <th> Model Number </th>  
  <th> Plan </th>
  <th> Plan Detail </th>
  <th> Activity Id </th>
  <th> Maintenance Date </th>  
  <th> Maintenance Due Date </th>
  </tr>';

 FOR i IN cur_maintenance_list (p_site_id)
         LOOP
          --SELECT (trunc(to_date(i."maintenance_date", 'DD-MON-RRRR') - 15)) into l_in_date from dua
          
            v_html_msg :=
                  v_html_msg
               || '<tr align="left"><td>'
               || i."Instrument_Number"
               || '</td><td>'
               || i."Instrument_Name"
               || '</td><td>'
               || i."EQP_Serial_Number"
               || '</td><td>'
               || i."Ownership"
               || '</td><td>'
               || i."Mfg_Name"
               || '</td><td>'
               || i."Model_Number"
               || '</td><td>'
               || i."Plan"
               || '</td><td>'
               || i."Plan_Detail"
               || '</td><td>'
               || i."Activity_Id"
               || '</td><td>'
               || i."Maintenance_Date"
               || '</td><td>'
               || i."Maintenance_Due_Date"
               || '</td>
              </Tr>';
         END LOOP;
         
      v_html_msg :=
               v_html_msg
            || '</table>
      <p>This is a system generated mail. Please do not reply on this mail.
       <br/>
       <br/>
       Regards,
       <br/>
       EQP.
      </p>
    </body>
  </html>';
  
   
  
  
  send_mail_recipient(p_to  => v_to,
            p_cc        => v_cc,
            p_bcc       => v_bcc,
            p_from      => v_from,
            p_subject   =>  'Mail notification about Maintenance Due for this week Equipment Management System',
            --p_text_msg  => v_txt_msg,
            p_html_msg  => v_html_msg,
            p_smtp_host => 'smtprelay.com'); 
            
             

END;
null;
END XX_EMS_MAIL_PRC_maintenance;

CodePudding user response:

Line 113 is

v_html_msg :=
              v_html_msg
           || '<tr align="left"><td>'
           ...

That variable is declared as

v_html_msg             VARCHAR2(32672)

which means that - as you're processing data in a loop - its length exceeds 32672 characters in length.

What to do? Use CLOB instead, or check whether there's really that much data (i.e. maybe cursor returned more rows than you'd expect - check its SELECT statement).

CodePudding user response:

The main problem is that v_html_msg is defined as VARCHAR2(32672) and the loop is trying to add more than 32672 characters there.

The full solution is to change v_html_msg datatype to CLOB. However, it will require you to refactor this procedure XX_EMS_MAIL_PRC_maintenance and other dependent one, like send_mail_recipient.

The workaround may be to send mail with only partial data (of course if it is OK with your business requirements). You can add an "if" in the loop so once the length of v_html_msg is larger than 32000 - stop adding more items there. For example:

 FOR i IN cur_maintenance_list (p_site_id)
         LOOP
            if length(v_html_msg) <30000 then --<<< NEW CODE
                v_html_msg :=
                      v_html_msg
                   || '<tr align="left"><td>'
                   || i."Instrument_Number"
                   || '</td><td>'
                   || i."Instrument_Name"
                   || '</td><td>'
                   || i."EQP_Serial_Number"
                   || '</td><td>'
                   || i."Ownership"
                   || '</td><td>'
                   || i."Mfg_Name"
                   || '</td><td>'
                   || i."Model_Number"
                   || '</td><td>'
                   || i."Plan"
                   || '</td><td>'
                   || i."Plan_Detail"
                   || '</td><td>'
                   || i."Activity_Id"
                   || '</td><td>'
                   || i."Maintenance_Date"
                   || '</td><td>'
                   || i."Maintenance_Due_Date"
                   || '</td>
                  </Tr>';
              else --<<< NEW CODE
                  v_html_msg :=
                      v_html_msg ||'... and more rows exist...';
              end if;
         END LOOP;

CodePudding user response:

You can refer to below link if you want your VARCHAR2 converted into CLOB.

Oracle: Changing VARCHAR2 column to CLOB

  • Related