【问题标题】:Need not to insert duplicate records into the main table instead want to update the existing record based on e_id不需要在主表中插入重复记录而是想根据 e_id 更新现有记录
【发布时间】:2022-01-02 14:26:22
【问题描述】:
CREATE TABLE new_details_staging 
(
    e_id         NUMBER(10),
    e_name       VARCHAR2(30),
    portal_desc  VARCHAR2(50),
    risk_dec     VARCHAR2(50),
    CONSTRAINT pk_new_details_staging PRIMARY KEY (e_id)
);

INSERT INTO new_details_staging 
VALUES (11, 'A', 'AA', 'High');

INSERT INTO new_details_staging 
VALUES (22, 'B', 'BB', 'Low');

CREATE TABLE lookup_ref 
(
    ref_id       NUMBER(10),
    ref_typ      VARCHAR2(30),
    ref_typ_desc VARCHAR2(20),
    CONSTRAINT pk_lookup_ref PRIMARY KEY (ref_id)
);

INSERT INTO lookup_ref 
VALUES (181, 'portal', 'AA');

INSERT INTO lookup_ref 
VALUES (182, 'portal', 'BB');

INSERT INTO lookup_ref 
VALUES (183, 'risk', 'High');

INSERT INTO lookup_ref 
VALUES (184, 'risk', 'Low');

CREATE TABLE new_details_main 
(
    e_id    NUMBER(10),
    e_name  VARCHAR2(30),
    portal  NUMBER(20),
    risk    NUMBER(20),
    CONSTRAINT pk_new_details_main PRIMARY KEY (e_id)
);

COMMIT;

存储过程

我想通过这个存储过程将记录从暂存中插入到主表中。

create or replace procedure sp_main(ov_err_msg OUT varchar2)
is
begin

INSERT INTO new_details_main (e_id, e_name, portal, risk)
SELECT n.e_id
,  n.e_name
,  (
   SELECT lp.ref_id
   FROM   lookup_ref lp -- lp is for Lookup-Portal
   WHERE  lp.ref_typ       = 'portal'
   AND    lp.ref_typ_desc  = n.portal_desc
  ),
  (
   SELECT lr.ref_id
   FROM   lookup_ref lr -- lr is for Lookup-Risk
   WHERE  lr.ref_typ       = 'risk'
   AND    lr.ref_typ_desc  = n.risk_dec
  )  
FROM  new_details_staging n
;
end;

此过程为我提供了所需的确切结果,但如果将数据添加到同一 e_id 的暂存表中,则它应该更新主表中的记录,而不是插入新记录。例如,

如果我截断临时表并插入一个新行,其中风险为低,但这次它被更新为高

INSERT INTO new_details_staging 
VALUES (22, 'B', 'BB', 'High');

所以,在我的主表中,应该只有 2 行,但对于 e_id 22,它应该已更新为 183。如何使用存储过程来实现这一点?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    我会说你需要MERGE

    这是一个例子。

    过程(为简单起见,我删除了OUT 参数;反正你没有使用它)。另外,我重写了它,使其不使用 portalrisk 值的子查询,而是加入同一个 (lookup_ref) 表两次(也许你需要使用外连接;你现在建议的数据你没有,但是 - 记住这一点):

    SQL> CREATE OR REPLACE PROCEDURE sp_main
      2  IS
      3  BEGIN
      4     MERGE INTO new_details_main m
      5          USING (SELECT n.e_id,
      6                        n.e_name,
      7                        lp.ref_id portal,
      8                        lr.ref_id risk
      9                   FROM new_details_staging n
     10                        JOIN lookup_ref lp
     11                           ON     lp.ref_typ_desc = n.portal_desc
     12                              AND lp.ref_typ = 'portal'
     13                        JOIN lookup_ref lr
     14                           ON     lr.ref_typ_desc = n.risk_dec
     15                              AND lr.ref_typ = 'risk') x
     16             ON (m.e_id = x.e_id)
     17     WHEN MATCHED
     18     THEN
     19        UPDATE SET m.e_name = x.e_name, m.portal = x.portal, m.risk = x.risk
     20     WHEN NOT MATCHED
     21     THEN
     22        INSERT     (e_id,
     23                    e_name,
     24                    portal,
     25                    risk)
     26            VALUES (x.e_id,
     27                    x.e_name,
     28                    x.portal,
     29                    x.risk);
     30  END;
     31  /
    
    Procedure created.
    

    测试:使用“初始”数据集(您发布的数据)运行程序:

    SQL> EXEC sp_main;
    
    PL/SQL procedure successfully completed.
    

    结果是:

    SQL> SELECT * FROM new_details_main;
    
          E_ID E_NAME         PORTAL       RISK
    ---------- ---------- ---------- ----------
            11 A                 181        183
            22 B                 182        184
    

    您说过您将从 staging 表中删除行并插入新行:

    SQL> DELETE FROM new_details_staging;
    
    2 rows deleted.
    
    SQL> INSERT INTO new_details_staging
      2  VALUES (22, 'B', 'BB', 'High');
    
    1 row created.
    

    让我们再次运行该程序并检查新结果:

    SQL> EXEC sp_main;
    
    PL/SQL procedure successfully completed.
    
    SQL> SELECT * FROM new_details_main;
    
          E_ID E_NAME         PORTAL       RISK
    ---------- ---------- ---------- ----------
            11 A                 181        183
            22 B                 182        183    --> RISK is modified to 183
    
    SQL>
    

    【讨论】:

      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 2014-05-18
      • 2020-07-19
      • 1970-01-01
      • 2023-01-12
      相关资源
      最近更新 更多