示例数据 - “执行包含更新和插入语句的存储过程时出现问题”

时间:2017-05-18 20:13:22

标签: oracle stored-procedures plsql

下面是我在“执行包含update和insert语句的存储过程时出问题”的问题的示例表和文件详细信息。以下是我在执行程序之前遵循的步骤。

  1. 我将从Vendor获取一个文件,其中包含以下格式的数据。

    6437,,01/01/2017,3483.92,,
    14081,,01/01/2017,8444.23,,
    
  2. 我正在将这些数据加载到表NMAC_PTMS_NOTEBK_SG中。在上面的文件中,第1列将是资产。

  3. 我正在使用名称为lse_id的额外列更新表格。现在NMAC_PTMS_NOTEBK_SG表将具有以下格式的数据。

    LSE_ID  AST_ID PRPRTY_TAX_DDCTN_CD LIEN_DT    ASES_PRT_1_AM ASES_PRT_2_AM
    5868087 5049   Null                01-01-2017 3693.3        NULL
    
  4. 现在我的程序将开始。在我的程序中,逻辑应该是我需要从lse_id获取NMAC_PTMS_NOTEBK_SG并在MJL表(此处为lse_id = app_lse_s)中进行比较。以下是MJL表格的结构。

    CREATE TABLE LPR_LP_TEST.MJL
    (
      APP_LSE_S     CHAR(10 BYTE)                   NOT NULL,
      DT_ENT_S      TIMESTAMP(3)                    NOT NULL, 
      DT_FOL_S      TIMESTAMP(3),
      NOTE_TYPE_S   CHAR(4 BYTE)                    NOT NULL,
      PRCS_C        CHAR(1 BYTE)                    NOT NULL,
      PRIO_C        CHAR(1 BYTE)                    NOT NULL,
      FROM_S        CHAR(3 BYTE)                    NOT NULL,
      TO_S          CHAR(3 BYTE)                    NOT NULL,
      NOTE_TITLE_S  VARCHAR2(41 BYTE)               NOT NULL,
      INFO_S        VARCHAR2(4000 BYTE),
      STAMP_L       NUMBER(10)                      NOT NULL,
      PRIVATE_C     CHAR(1 BYTE),
      LSE_ACC_C     CHAR(1 BYTE),
      COL_STAT_S    CHAR(4 BYTE),
      INFO1_S       VARCHAR2(250 BYTE),
      INFO2_S       VARCHAR2(250 BYTE),
      INFO3_S       VARCHAR2(250 BYTE),
      INFO4_S       VARCHAR2(250 BYTE),
      NTBK_RSN_S    CHAR(4 BYTE)
    )
    TABLESPACE LPR_LP_TEST
    PCTUSED    0
    PCTFREE    25
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
    )
    LOGGING 
    NOCOMPRESS 
    NOCACHE
    NOPARALLEL
    MONITORING;
    
    CREATE UNIQUE INDEX LPR_LP_TEST.MJL_IDX0 ON LPR_LP_TEST.MJL
    (APP_LSE_S, DT_ENT_S)
    LOGGING
    TABLESPACE LPR_LP_TEST
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
        INITIAL          64K
        NEXT             1M
        MINEXTENTS       1
        MAXEXTENTS       UNLIMITED
        PCTINCREASE      0
        BUFFER_POOL      DEFAULT
    )
    NOPARALLEL;
    
    CREATE OR REPLACE TRIGGER LPR_LP_TEST."MT_MJL_AIUD" 
    AFTER INSERT OR UPDATE OR DELETE ON mjl
    BEGIN
    mpkg_trig_mjl.mp_mjl_aiud;
    END mt_mjl_aiud;
    / 
    
    CREATE OR REPLACE TRIGGER LPR_LP_TEST."MT_MJL_AIUDR" 
    AFTER INSERT OR UPDATE OR DELETE ON mjl FOR EACH ROW
    BEGIN
    mpkg_trig_mjl.mp_mjl_aiudr (INSERTING, UPDATING, DELETING,
                :NEW.app_lse_s, :NEW.prcs_c, :NEW.note_type_s,
                :OLD.app_lse_s, :OLD.prcs_c, :OLD.note_type_s);
    END mt_mjl_aiudr;
    /
    
    CREATE OR REPLACE TRIGGER LPR_LP_TEST."MT_MJL_BIUD" 
    BEFORE INSERT OR UPDATE OR DELETE ON mjl
    BEGIN
    mpkg_trig_mjl.mp_mjl_biud;
    END mt_mjl_biud;
    /
    
    CREATE OR REPLACE TRIGGER LPR_LP_TEST."MT_MJL_OBIUR" 
    BEFORE INSERT OR UPDATE ON mjl FOR EACH ROW
    BEGIN
    IF INSERTING THEN
        :NEW.stamp_l := mpkg_util.mp_time_ticker;
    ELSE
        IF :OLD.stamp_l > 999999990 THEN
            :NEW.stamp_l := 1;
        ELSE
            :NEW.stamp_l := :OLD.stamp_l + 1;
        END IF;
    END IF;
    END mt_mjl_obiur;
    /     
    
  5. 以下是我在上一篇文章中提供的程序,它几乎对我有用。

  6. CREATE OR REPLACE PROCEDURE LPR_LP_TEST.SP_PTMS_NOTES
          (
          p_app_lse_s     IN mjl.app_lse_s%TYPE,
          --p_dt_ent_s      IN mjl.dt_ent_s%TYPE,
          --p_note_type_s   IN mjl.note_type_s%TYPE,
          --p_prcs_c        IN mjl.prcs_c%TYPE,
          --p_prio_c        IN mjl.prio_c%TYPE,
          --p_note_title_s  IN mjl.note_title_s%TYPE,
          --p_info1_s       IN mjl.info1_s%TYPE,
          --p_info2_s       IN mjl.info2_s%TYPE
          )
          AS
          --v_rowcount_i   number;
          --v_lien_date    mjl.info1_s%TYPE;
          --v_lien_date    NMAC_PTMS_NOTEBK_SG.LIEN_DT%TYPE;
          --v_asst_amount  mjl.info2_s%TYPE;
          v_app_lse_s    mjl.app_lse_s%TYPE;
    BEGIN
          v_app_lse_s := trim(p_app_lse_s);
    
          -- I hope this dbms_output line is for temporary debug purposes only
          -- and will be removed in the production version!
          dbms_output.put_line(app_lse_s);
    
          merge into mjl tgt
          using (select lse_s app_lse_s,
                        sysdate dt_ent_s,
                        'SPPT' note_type_s,
                        'Y' prcs_c,
                        '1' prio_c,
                        'Property Tax Assessment' note_title_s,
                        lien_dt info1_s,
                        ases_prt_1_am info2_s
                 from   nmac_ptms_notebk_sg
                 where  lse_id = v_app_lse_s) src
          on (trim(tgt.app_lse_s) = trim(src.app_lse_s))
            -- and tgt.dt_ent_s = src.dt_ent_s) 
          when matched then
          update set --tgt.dt_ent_s = src.dt_ent_s,
                     tgt.note_title_s = src.note_title_s,
                     tgt.info1_s = src.info1_s,
                     tgt.info2_s = src.info2_s
          where --tgt.dt_ent_s != src.dt_ent_s
             tgt.note_title_s != src.note_title_s
          or    tgt.info1_s != src.info1_s
          or    tgt.info2_s != src.info2_s
          when not matched then
          insert (tgt.app_lse_s,
                  tgt.dt_ent_s,
                  tgt.note_type_s,
                  tgt.prcs_c,
                  tgt.prio_c,
                  tgt.from_s,
                  tgt.to_s,
                  tgt.note_title_s,
                  tgt.info1_s,
                  tgt.info2_s)
          values (src.app_lse_s,
                  src.dt_ent_s,
                  src.note_type_s,
                  src.prcs_c,
                  src.prio_c,
                  src.from_s,
                  src.to_s,
                  src.note_title_s,
                  src.info1_s,
                  src.info2_s);
    
          commit;
    end;
    
    1. 现在逻辑应该是我需要从我的文件中传递lse_id 已经保存到程序中。
    2. 如果我传递的lse_idapp_lse_s匹配 mjl表然后我需要更新该行和一些被编码的 我正在做的字段是关联的。
    3. 如果lse_id不匹配,那么我必须为此插入一个新行 租约和硬编码字段。
    4. 我面临的问题是dt_ent_s表中的mjl是一个 独特的约束。
    5. 如果以上内容对你有意义,请告诉我......

1 个答案:

答案 0 :(得分:2)

  

“我面临的问题是mjl表中的dt_ent_s是一个唯一约束。”

实际上并非如此,它是复合唯一键的一部分。所以你的ON子句应该匹配

on (tgt.app_lse_s  = src.app_lse_s
    and tgt.dt_ent_s = src.dt_ent_s)

顺便说一句,在ON子句中使用trim()令人担忧,尤其是trim(tgt.app_lse_s)。如果您要插入带尾随或前导空格的值,则“唯一键”会在您修剪它们时产生多次点击。从文件加载数据并在表中插入修剪后的值时,应修剪空格。

  

“ORA-00001:违反了唯一约束(LPR_LP_TEST.MJL_IDX0)”

MJL_IDX0必须是一个独特的索引。这意味着您需要在考虑唯一记录的情况下包含其列。

显然,您的直接INSERT逻辑和MERGE INSERT逻辑之间存在差异。您需要比较这两个陈述并找出差异。