Search code examples
oracleexceptionplsqlcursor

Calling Cursor Value into Exception


I have a cursor as part of a package, which compares the counts of 2 tables. If the counts match, rest of the package executes. But if it fails, it should update the counts in a log table. The cursor code is

    CURSOR C_CNT IS
      SELECT
        lnd.sml_batchrun_id batch_id,
        lnd.lnd_count,
        dwh.dwh_count
      FROM
        (
         SELECT
          sml_batchrun_id,
          COUNT(*) lnd_count
         FROM
          iva_landing.lnd_sml_t
        GROUP BY
          sml_batchrun_id
        ) lnd
       LEFT JOIN (
        SELECT
         batchrun_id,
         sent_records_count dwh_count,
         dwh_sending_table
        FROM
         dwh.dwh_idh_to_iva_metadata_t
         ) dwh ON dwh.batchrun_id = lnd.sml_batchrun_id
        WHERE dwh.dwh_sending_table = 'DWH_SML_T'
        ORDER BY
      1 DESC;

The comparison code is:

    FOR L_COUNT IN C_CNT LOOP        --0001,0002
      IF L_COUNT.lnd_count = L_COUNT.dwh_count THEN
       UPDATE DWH.DWH_IDH_TO_IVA_METADATA_T idh
       SET idh.IVA_RECEIVING_TABLE = 'LND_SML_T',
       idh.RECEIVED_DATE = SYSDATE,
       idh.RECEIVED_RECORDS_COUNT = L_COUNT.lnd_count,
       idh.status = 'Verified'
       WHERE L_COUNT.batch_id = idh.batchrun_id
       AND idh.dwh_sending_table = 'DWH_SML_T';
       COMMIT;
      ELSE
       RAISE  EXCPT_SML_MISSDATA;  -- Throw  error and exit process 
      END IF;
     END LOOP;

Now, in the Exception Handling part, I want to display the counts in the error column of the log table

    logger.log_error('IVA-MSG 200-010 - COUNT MISMATCH! - Aborting',  p_log_id=>l_job_log.log_id);
     l_job_log.end_date     := systimestamp;
     l_job_log.error_mesg   := cur_cnt.dwh_count||' '|| cur_cnt.lnd_count;
     l_job_log.status       := iva_log.iva_job_log_pck.c_str_statusfailed;
     iva_log.iva_job_log_pck.change_joblog_prc(pi_rec_joblog => l_job_log);
     RAISE;

Here, cur_cnt is a variable defined as cur_cnt c_cnt%rowtype; and l_job_log as l_job_log iva_log.iva_job_log_t%rowtype;

where iva_job_log_t is the log table name. But after triggering the package the count is not visible in the error column. Also, if I put something in single quotes for the iva_job_log_t then it gets displayed in the log table.

Please suggest how to display the counts from the cursor.

Thanks


Solution

  • If you are still doing

    FOR L_COUNT IN C_CNT LOOP
    

    then your cur_cnt variable is never going to be populated; it will be the empty record it was declared as, so referring to any of its fields will always give you null.

    You can just refer to the l_count values in the error log:

    l_job_log.error_mesg := l_count.dwh_count ||' '|| l_count.lnd_count;
    

    ... as you do elsewhere inside the loop.

    If the exception handler is currently later in the process, so l_count is out of scope (as the re-raise possibly suggests) then you could move it so it's within the else instead of being separated:

    FOR L_COUNT IN C_CNT LOOP        --0001,0002
      IF L_COUNT.lnd_count = L_COUNT.dwh_count THEN
       UPDATE DWH.DWH_IDH_TO_IVA_METADATA_T idh
       SET idh.IVA_RECEIVING_TABLE = 'LND_SML_T',
       idh.RECEIVED_DATE = SYSDATE,
       idh.RECEIVED_RECORDS_COUNT = L_COUNT.lnd_count,
       idh.status = 'Verified'
       WHERE L_COUNT.batch_id = idh.batchrun_id
       AND idh.dwh_sending_table = 'DWH_SML_T';
       COMMIT;
      ELSE
       logger.log_error('IVA-MSG 200-010 - COUNT MISMATCH! - Aborting',  p_log_id=>l_job_log.log_id);
       l_job_log.end_date     := systimestamp;
       l_job_log.error_mesg   := l_count.dwh_count||' '|| l_count.lnd_count;
       l_job_log.status       := iva_log.iva_job_log_pck.c_str_statusfailed;
       iva_log.iva_job_log_pck.change_joblog_prc(pi_rec_joblog => l_job_log);
       RAISE  EXCPT_SML_MISSDATA;  -- Throw  error and exit process 
      END IF;
     END LOOP;
    

    Otherwise you would have to change the cursor loop handling to fetch into the variable, refer to that within the loop instead, and rely on that having the right values later:

    OPEN C_CNT
    LOOP
      FETCH C_CNT INTO CUR_CNT;
      EXIT WHEN C_CNT%NOTFOUND;
    
      IF CUR_CNT.lnd_count = CUR_CNT.dwh_count THEN
       UPDATE DWH.DWH_IDH_TO_IVA_METADATA_T idh
       SET idh.IVA_RECEIVING_TABLE = 'LND_SML_T',
       idh.RECEIVED_DATE = SYSDATE,
       idh.RECEIVED_RECORDS_COUNT = CUR_CNT.lnd_count,
       idh.status = 'Verified'
       WHERE CUR_CNT.batch_id = idh.batchrun_id
       AND idh.dwh_sending_table = 'DWH_SML_T';
       COMMIT;
      ELSE
       RAISE  EXCPT_SML_MISSDATA;  -- Throw  error and exit process 
      END IF;
     END LOOP;
    

    Your later exception handler should then work as it is.