不需要在主 table 中插入重复记录,而是希望根据 e_id 更新现有记录

Need not to insert duplicate records into the main table instead want to update the existing record based on e_id

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;

存储过程

我想通过这个存储过程将记录插入主table。

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 的数据添加到分段 table 中,则它应该更新主 [=27= 中的记录] 而不是插入新记录。例如,

如果我截断分期 table 并插入一个风险为低的新行,但这次它已更新为高

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

因此,在我的主 table 中,应该只有 2 行,但对于 e_id 22,它应该已更新为 183。我如何使用存储过程实现此目的?

我会说你需要 MERGE

这是一个例子。

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

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 table 中删除行并插入一个新行:

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>