【问题标题】:Merging replaces existing values in database with null though using nvl()合并使用 nvl() 将数据库中的现有值替换为 null
【发布时间】:2021-06-18 08:36:46
【问题描述】:

下面的存储过程工作正常,但合并使用 nvl() 将数据库中的现有值替换为 null

  create or replace PROCEDURE P_UPSERT_CONNECTDISCONNECT
(
  I_SAP_UUID IN VARCHAR2 DEFAULT NULL
, I_METER_ID IN VARCHAR2 
, I_STATUS IN VARCHAR2 
, I_CUR_SYSTEM IN VARCHAR2 
, I_REQ_CREATION_TIME IN DATE DEFAULT NULL
, I_CAT_CODE IN VARCHAR2 DEFAULT NULL
, I_PLANNED_TIME IN DATE DEFAULT NULL
, I_ASB_REC_TIME IN DATE DEFAULT NULL
, I_MDM_REC_TIME IN DATE DEFAULT NULL
, I_LOAD_ACT_CODE IN VARCHAR2 DEFAULT NULL
, I_NRT_REC_TIME IN DATE DEFAULT NULL
, I_NRT_VER_REC_TIME IN DATE DEFAULT NULL
, I_CONF_UUID IN VARCHAR2 DEFAULT NULL
, I_ERROR_DETAIL IN VARCHAR2 DEFAULT NULL
) AS 
BEGIN
  MERGE INTO CONNECTDISCONNECT e
     using (select I_SAP_UUID SAP_UUID, I_METER_ID METER_ID,I_STATUS STATUS, I_CUR_SYSTEM CUR_SYSTEM, I_REQ_CREATION_TIME REQ_CREATION_TIME, I_CAT_CODE CAT_CODE, I_PLANNED_TIME PLANNED_TIME,I_ASB_REC_TIME ASB_REC_TIME,I_MDM_REC_TIME MDM_REC_TIME,I_LOAD_ACT_CODE LOAD_ACT_CODE,I_NRT_REC_TIME NRT_REC_TIME,I_NRT_VER_REC_TIME NRT_VER_REC_TIME,I_CONF_UUID CONF_UUID,I_ERROR_DETAIL ERROR_DETAIL   from dual) s
  on (e.METER_ID = s.METER_ID) 
    WHEN MATCHED THEN
            UPDATE SET SAP_UUID      = nvl(I_SAP_UUID, s.SAP_UUID),
                   STATUS            = nvl(I_STATUS, s.STATUS),
                   CUR_SYSTEM        = nvl(I_CUR_SYSTEM, s.CUR_SYSTEM),
                   REQ_CREATION_TIME = nvl(I_REQ_CREATION_TIME, s.REQ_CREATION_TIME),
                   CAT_CODE          = nvl(I_CAT_CODE, s.CAT_CODE),
                   PLANNED_TIME      = nvl(I_PLANNED_TIME, s.PLANNED_TIME),
                   ASB_REC_TIME      = nvl(I_ASB_REC_TIME, s.ASB_REC_TIME),
                   MDM_REC_TIME      = nvl(I_MDM_REC_TIME, s.MDM_REC_TIME),
                   LOAD_ACT_CODE     = nvl(I_LOAD_ACT_CODE, s.LOAD_ACT_CODE),
                   NRT_REC_TIME      = nvl(I_NRT_REC_TIME, s.NRT_REC_TIME),
                   NRT_VER_REC_TIME  = nvl(I_NRT_VER_REC_TIME, s.NRT_VER_REC_TIME),
                   CONF_UUID         = nvl(I_CONF_UUID, s.CONF_UUID),
                   ERROR_DETAIL      = nvl(I_ERROR_DETAIL, s.ERROR_DETAIL)
    WHEN NOT MATCHED THEN
      INSERT (e.SAP_UUID, e.METER_ID, e.STATUS, e.CUR_SYSTEM,e.REQ_CREATION_TIME,e.CAT_CODE,e.PLANNED_TIME,e.ASB_REC_TIME,e.MDM_REC_TIME,e.LOAD_ACT_CODE,e.NRT_REC_TIME,e.NRT_VER_REC_TIME,e.CONF_UUID,e.ERROR_DETAIL)
      VALUES (s.SAP_UUID, s.METER_ID, s.STATUS, s.CUR_SYSTEM,s.REQ_CREATION_TIME,s.CAT_CODE,s.PLANNED_TIME,s.ASB_REC_TIME,s.MDM_REC_TIME,s.LOAD_ACT_CODE,s.NRT_REC_TIME,s.NRT_VER_REC_TIME,s.CONF_UUID,s.ERROR_DETAIL);
END;

【问题讨论】:

    标签: sql oracle plsql oracle11g null


    【解决方案1】:

    如果它们是可选的,则将它们声明为

    create or replace PROCEDURE P_UPSERT_CONNECTDISCONNECT
    (
      I_SAP_UUID IN VARCHAR2 DEFAULT NULL
    , I_METER_ID IN VARCHAR2 DEFAULT NULL
    

    而 - 在过程中 - 你必须决定在它们没有任何价值的情况下该怎么做。

    您的代码可以简化为

    UPDATE SET 
    SAP_UUID = Case When (I_SAP_UUID is not null and I_SAP_UUID <> '') Then I_SAP_UUID Else e.SAP_UUID End,
    

    update set
    s.sap_uuid = nvl(i_sap_uuid, e.sap_uuid),
    

    此外,由于在 Oracle 中 null 等于空字符串,您不必检查两次,例如

    I_SAP_UUID is not null and I_SAP_UUID <> ''
    

    只是

    I_SAP_UUID is not null
    

    【讨论】:

    • nvl(I_REQ_CREATION_TIME, s.REQ_CREATION_TIME) , REQ_CREATION_TIME 有一个日期值,但它正在更新为 NULL .. 任何线索??
    • 我应该为 NVL 工作的日期字段做些什么
    • 不,就 NVL 而言,DATE 数据类型没有什么特别之处。如果可能,通过编辑您发布的原始问题创建一个小示例(仅相关列/参数),以便我们可以尝试重现您描述的问题。
    • 我将空值传递给存储过程输入,但它正在用 NULL 替换现有值。我错过了什么吗??
    • 您可能无法重现该问题,因为我正在从基于 Eclipse 的工具中调用该过程。
    【解决方案2】:

    您可以使用 DEFAULT 指定默认值,如果未提供参数,将分配该值:

    create or replace PROCEDURE P_UPSERT_CONNECTDISCONNECT
    (
      I_SAP_UUID IN VARCHAR2 DEFAULT NULL
    , I_METER_ID IN VARCHAR2 DEFAULT NULL
    , I_STATUS IN VARCHAR2   DEFAULT NULL
    , I_CUR_SYSTEM IN VARCHAR2 DEFAULT NULL
    ....
    

    另一种方法是创建重载过程(同名不同参数的过程):

    CREATE PROCEDURE P_UPSERT_CONNECTDISCONNECT(I_SAP_UUID IN VARCHAR2, I_METER_ID IN VARCHAR2) AS
    BEGIN
      -- 2 arguments 
    END P_UPSERT_CONNECTDISCONNECT;
    
    CREATE PROCEDURE P_UPSERT_CONNECTDISCONNECT(I_SAP_UUID IN VARCHAR2, I_METER_ID IN VARCHAR2, I_STATUS IN VARCHAR2) AS
    BEGIN
      -- 3 arguments 
    END P_UPSERT_CONNECTDISCONNECT;
    

    【讨论】:

      猜你喜欢
      • 2015-07-10
      • 1970-01-01
      • 2015-01-31
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 1970-01-01
      相关资源
      最近更新 更多