数据未通过 Oracle 中的存储过程更新

问题描述 投票:0回答:1

我写了一个基于

SAP_ID
的 SP,如果该 SAPID 的数据已经存在,我将更新表上的数据,如果不存在,则插入它。

以下是我的询问:

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;

我哪里出错了?

oracle-database stored-procedures
1个回答
0
投票

您从未解释过您说您编写的程序不起作用的意思。你是怎么检查的?你运行了吗?使用哪些数据?您检查过

OUT
参数的值吗?

无论如何:不要检查行是否已经存在(或不存在)并编写单独的

update
insert
语句,而是考虑使用
merge
代替;它也称为“upsert”,因为它将更新与插入结合在一起,专为您描述的问题而设计。

这是一个简化的示例(我不想创建所有这些参数或表列),但是 - 它应该说明我想说的内容。

示例表和顺序:

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.

程序;它删除了代码的logging部分 - 如果需要的话,将其包含回来。基本上,它通过检查目标表中是否存在

P_SAP_ID
行来完成与您的过程相同的工作:

  • 如果存在,
    merge
    将更新该行
  • 如果没有,它将插入一个新行

这是它的代码:

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.

让我们测试一下:第一个示例运行正常并插入一行:

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

此示例因日期值无效而失败(并返回错误消息):

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.

最后一个示例更新现有行:

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>

所以,是的 - 它有效。仔细看看它 - 如果您发现它有用 - 重写您的代码,使其与我的示例过程相同。

© www.soinside.com 2019 - 2024. All rights reserved.