不需要在主 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
参数;反正您也没有使用它)。另外,我重写了它,这样它就不会对 portal
和 risk
值使用子查询,而是加入相同的 (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>
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
参数;反正您也没有使用它)。另外,我重写了它,这样它就不会对 portal
和 risk
值使用子查询,而是加入相同的 (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>