oracle-databasestored-procedures

Data not getting updated via stored procedure in Oracle


I have written a stored procedure where based on the SAP_ID, I will update the data in the table, if the data for that SAP_ID already exists, if not, then I INSERT it.

This is my query:

PROCEDURE INSERT_PF_EXCEL_DATA_IPCOLO (
        p_political_state_name         IN NVARCHAR2,
        p_political_state_code         IN NVARCHAR2,
        p_rfcdate                      IN NVARCHAR2,
        p_rfs_date                     IN NVARCHAR2,
        p_rfe1_date                    IN NVARCHAR2,
        p_site_drop_date               IN NVARCHAR2,
        p_ip_colo_siteid               IN NVARCHAR2,
        p_mw_installed                 IN NVARCHAR2,
        p_dg_nondg                     IN NVARCHAR2,
        p_eb_noneb                     IN NVARCHAR2,
        p_id_od_countchange            IN NVARCHAR2,
        p_id_od_changeddate            IN NVARCHAR2,
        p_rrh_countchange              IN NVARCHAR2,
        p_rrh_changeddate              IN NVARCHAR2,
        p_tenancy_countchange          IN NVARCHAR2,
        p_tenancy_changeddate          IN NVARCHAR2,
        p_sap_id                       IN NVARCHAR2,
        p_created_by                   IN NVARCHAR2,
        p_rfs_date_5g                  IN NVARCHAR2,
        p_drop_date_5g                 IN NVARCHAR2,
        p_olt_count                    IN NUMBER,
        p_olt_change_date              IN NVARCHAR2,
        p_diesel_downtime_minutes      IN NVARCHAR2,
        p_overall_infra_outage_minutes IN NVARCHAR2,
        p_diesel_downtime_min_my       IN NVARCHAR2,
        p_overall_infra_outage_min_my  IN NVARCHAR2,
        p_is5gpresent                  IN NVARCHAR2,
        p_is_site_dropped              IN NVARCHAR2,
        p_status                       OUT NVARCHAR2,
        p_message                      OUT NVARCHAR2
    ) AS
        t_cnt           NUMBER;
        vcnt_sapid      NUMBER;
        v_ipcolobilling VARCHAR2(25) := 'IpColoBilling';
    BEGIN

  --  DELETE FROM APP_LOG WHERE APP_NAME = 'IpColoBilling' AND TRUNC(LOG_TIME) = TRUNC(SYSDATE - 2);

        DELETE FROM app_log
        WHERE
                app_name = v_ipcolobilling
            AND ( log_time ) >= trunc(sysdate - 2)
            AND log_time < trunc(sysdate - 1);

        COMMIT;
        
        SELECT count(sap_id) INTO vcnt_sapid FROM temp_ipcolo_billing_mst
        WHERE
            sap_id = p_sap_id;-- AND CREATED_DATE = SYSDATE;


        IF vcnt_sapid > 0 THEN
            UPDATE temp_ipcolo_billing_mst
SET
    political_state_name = p_political_state_name,
    political_state_code = p_political_state_code,
    rfcdate = TO_DATE(p_rfcdate, 'DD-MM-YYYY'), -- Truncates to the day
    rfs_date = TO_DATE(p_rfs_date, 'DD-MM-YYYY'),-- TRUNC(), -- Removed invalid format 'dd-MM-yyyy'
    rfe1_date = TO_DATE(p_rfe1_date, 'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
   site_drop_date = TO_DATE(p_site_drop_date,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    ip_colo_siteid = p_ip_colo_siteid,
    mw_installed = p_mw_installed,
    dg_nondg = p_dg_nondg,
    eb_noneb = p_eb_noneb,
    id_od_countchange = p_id_od_countchange,
    id_od_changeddate = TO_DATE(p_id_od_changeddate,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    rrh_countchange = p_rrh_countchange,
    rrh_changeddate = TO_DATE(p_rrh_changeddate,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    tenancy_countchange = p_tenancy_countchange,
    tenancy_changeddate = TO_DATE(p_tenancy_changeddate,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    created_by = p_created_by,
    rfs_date_5g = TO_DATE(p_rfs_date_5g,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    drop_date_5g = TO_DATE(p_drop_date_5g,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    olt_count = p_olt_count,
    olt_change_date = TO_DATE(p_olt_change_date,'DD-MM-YYYY'), -- Removed invalid format 'dd-MM-yyyy'
    diesel_downtime_minutes = p_diesel_downtime_minutes,
    overall_infra_outage_minutes = p_overall_infra_outage_minutes,
    diesel_downtime_min_my = p_diesel_downtime_min_my,
    overall_infra_outage_min_my = p_overall_infra_outage_min_my,
    is5gpresent = p_is5gpresent,
    is_site_dropped = p_is_site_dropped,
    LAST_UPDATED_DATE = SYSDATE
    
WHERE

    sap_id = p_sap_id;
                
                p_message := 'SUCCESS';

            COMMIT;
        ELSE
            INSERT INTO temp_ipcolo_billing_mst (--TEMP_IPCOLO_BILLING_MST

                id,
                political_state_name,
                political_state_code,
                rfcdate,
                rfs_date,
                rfe1_date,
                site_drop_date,
                ip_colo_siteid,
                mw_installed,
                dg_nondg,
                eb_noneb,
                id_od_countchange,
                id_od_changeddate,
                rrh_countchange,
                rrh_changeddate,
                tenancy_countchange,
                tenancy_changeddate,
                sap_id,
                created_by,
                rfs_date_5g,
                drop_date_5g,
                olt_count,
                olt_change_date,
                diesel_downtime_minutes,
                overall_infra_outage_minutes,
                diesel_downtime_min_my,
                overall_infra_outage_min_my,
                is5gpresent,
                is_site_dropped
            ) VALUES (
                incr_id_ipcolo_temp.NEXTVAL,
                p_political_state_name,
                p_political_state_code,
                to_date(p_rfcdate, 'dd-MM-yyyy'),
                to_date(p_rfs_date, 'dd-MM-yyyy'),
                to_date(p_rfe1_date, 'dd-MM-yyyy'),
                to_date(p_site_drop_date, 'dd-MM-yyyy'),
                p_ip_colo_siteid,
                p_mw_installed,
                p_dg_nondg,
                p_eb_noneb,
                p_id_od_countchange,
                to_date(p_id_od_changeddate, 'dd-MM-yyyy'),
                p_rrh_countchange,
                to_date(p_rrh_changeddate, 'dd-MM-yyyy'),
                p_tenancy_countchange,
                to_date(p_tenancy_changeddate, 'dd-MM-yyyy'),
                p_sap_id,
                p_created_by,
                to_date(p_rfs_date_5g, 'dd-MM-yyyy'),
                to_date(p_drop_date_5g, 'dd-MM-yyyy'),
                p_olt_count,
                to_date(p_olt_change_date, 'dd-MM-yyyy'),
                p_diesel_downtime_minutes,
                p_overall_infra_outage_minutes,
                to_date(p_diesel_downtime_min_my, 'dd-MM-yyyy'), 
                to_date(p_overall_infra_outage_min_my, 'dd-MM-yyyy'),
                p_is5gpresent,
                p_is_site_dropped
            );

            p_message := 'SUCCESS';
        END IF;

    EXCEPTION
        WHEN OTHERS THEN
            p_status := sqlerrm;
            p_message := 'ERROR';
    END INSERT_PF_EXCEL_DATA_IPCOLO;

Where am I going wrong?


Solution

  • You never explained what you meant by saying that procedure you wrote doesn't work. How did you check it? Did you run it? Using which data? Did you check value of OUT parameters?

    Anyway: instead of checking whether row already exists (or not) and writing separate update and insert statements, consider using merge instead; it is also known as "upsert" as it combines update with insert, and is designed for problems you described.

    Here's a simplified example (I didn't feel like creating all those parameters or table columns), but - it should illustrate what I'm trying to say.

    Sample table and sequence:

    SQL> create table temp_ipcolo_billing_mst
      2  (id                   number,
      3   political_state_name varchar2(10),
      4   political_state_code varchar2(10),
      5   rfcdate              date);
    
    Table created.
    
    SQL> create sequence incr_id_ipcolo_temp;
    
    Sequence created.
    

    Procedure; it removed logging part of code - include it back, if you need it. Basically, it does the same job as your procedure by checking whether P_SAP_ID row exists in the target table or not:

    Here's its code:

    SQL> create or replace procedure insert_pf_excel_data_ipcolo
      2    (p_sap_id               in number,
      3     p_political_state_name in nvarchar2,
      4     p_political_state_code in nvarchar2,
      5     p_rfcdate              in nvarchar2,
      6     p_message             out nvarchar2)
      7  as
      8  begin
      9      merge into temp_ipcolo_billing_mst a
     10      using (select p_sap_id               as sap_id,
     11                    p_political_state_name as political_state_name,
     12                    p_political_state_code as political_state_code,
     13                    to_date(p_rfcdate, 'dd-mm-yyyy')   as rfcdate
     14            from dual
     15           ) b
     16        on (b.sap_id = a.id)
     17      when matched then update set
     18        a.political_state_name = b.political_state_name,
     19        a.political_state_code = b.political_state_code,
     20        a.rfcdate   = b.rfcdate
     21      when not matched then insert
     22        (id,
     23         political_state_name,
     24         political_state_code,
     25         rfcdate)
     26        values
     27        (incr_id_ipcolo_temp.nextval,
     28         b.political_state_name,
     29         b.political_state_code,
     30         b.rfcdate
     31        );
     32
     33    p_message := 'SUCCESS';
     34  exception
     35    when others then
     36      p_message := 'ERROR: ' || sqlerrm;
     37  end;
     38  /
    
    Procedure created.
    

    Let's test it: the first example runs OK and inserts a row:

    SQL> set serveroutput on
    SQL> declare
      2    l_msg varchar2(200);
      3  begin
      4    insert_pf_excel_data_ipcolo
      5      (p_sap_id               => 1,
      6       p_political_state_name => 'Pol. name',
      7       p_political_state_code => 'PNC',
      8       p_rfcdate              => '06-01-2025',
      9       p_message              => l_msg);
     10    dbms_output.put_line(l_msg);
     11  end;
     12  /
    SUCCESS
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from temp_ipcolo_billing_mst;
    
            ID POLITICAL_ POLITICAL_ RFCDATE
    ---------- ---------- ---------- ---------
             1 Pol. name  PNC        06-JAN-25
    

    This example fails because of invalid date value (and returns error message):

    SQL> declare
      2    l_msg varchar2(200);
      3  begin
      4    insert_pf_excel_data_ipcolo
      5      (p_sap_id               => 1,
      6       p_political_state_name => 'Pol. name',
      7       p_political_state_code => 'PNC',
      8       p_rfcdate              => '99-01-2025',
      9       p_message              => l_msg);
     10    dbms_output.put_line(l_msg);
     11  end;
     12  /
    ERROR: ORA-01847: day of month must be between 1 and last day of month
    
    PL/SQL procedure successfully completed.
    

    The final example updates existing row:

    SQL> declare
      2    l_msg varchar2(200);
      3  begin
      4    insert_pf_excel_data_ipcolo
      5      (p_sap_id               => 1,
      6       p_political_state_name => 'Pol. nameA',
      7       p_political_state_code => 'PNC_A',
      8       p_rfcdate              => '25-08-2025',
      9       p_message              => l_msg);
     10    dbms_output.put_line(l_msg);
     11  end;
     12  /
    SUCCESS
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from temp_ipcolo_billing_mst;
    
            ID POLITICAL_ POLITICAL_ RFCDATE
    ---------- ---------- ---------- ---------
             1 Pol. nameA PNC_A      25-AUG-25
    
    SQL>
    

    So, yes - it works. Have a closer look at it and - if you find it useful - rewrite your code so that it does the same as my sample procedure.