oracle - 将 MERGE 与 Oracle 存储过程一起使用
问题描述
如果它不存在,我正在尝试将记录插入到我的表中。如果它确实存在,我希望它更新。
我看到其他人发布的这个例子:
MERGE INTO mytable d
USING (SELECT 1 id, 'x' name from dual) s
ON (d.id = s.id)
WHEN MATCHED THEN UPDATE SET d.name = s.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);
我当前的存储过程如下所示:
procedure savePublicId(P_ACCNO in varchar2, P_PUBLICID in varchar2) is
begin
update cc_custprofiles cpr
set cpr.publicid = P_PUBLICID
where cpr.customerlong_cpr = 'C'||P_ACCNO
and key_cpr = 'SINGLE';
commit;
end;
此表中没有身份列(我知道......)所以我无法捕捉。我试图改变它merge
以匹配我的表结构,但我是 Oracle 的新手,所以不太确定我在做什么:D
我想出了这个:
merge into cc_custprofiles cpr
using (select 1 customerlong_cpr, 'x' publicid, 'SINGLE' key_cpr from dual) dual
on (cpr.customerlong_cpr = dual.customerlong_cpr)
when matched then update set cpr.publicid = P_PUBLICID
WHEN NOT MATCHED THEN INSERT (customerlong_cpr, publicid, key_cpr) values (P_ACCNO, P_PUBLICID, 'SINGLE');
但我认为这是不对的。有人可以帮我吗?
解决方案
您的合并语句快到了。我认为你追求的是更像这样的东西:
MERGE INTO cc_custprofiles tgt
USING (SELECT 'C' || p_accno customerlong_cpr,
p_publicid publicid,
'SINGLE' key_cpr
FROM dual) src
ON (tgt.customerlong_cpr = src.customerlong_cpr AND tgt.key_cpr = src.key_cpr)
WHEN MATCHED THEN
UPDATE SET tgt.publicid = src.publicid
WHEN NOT MATCHED THEN
INSERT (tgt.customerlong_cpr, tgt.publicid, tgt.key_cpr)
VALUES (src.customerlong_cpr, src.publicid, src.key_cpr);
合并语句的要点是从源表或子查询中获取结果,并决定是在目标表中插入还是更新它们。在您的情况下,由于您使用参数来决定插入什么,因此您需要将它们放入select ... from dual
子查询中,以便您可以将其用作合并语句中的源子查询。
您的连接条件(又名ON
子句)是您用来识别行的谓词 - 在您的情况下,这似乎是:
where cpr.customerlong_cpr = 'C'||P_ACCNO
and key_cpr = 'SINGLE';
从您的更新声明中。
然后只需根据需要更新或插入相关值即可。
注意我总是分别使用tgt
和src
作为目标表和源表/子查询的别名;我发现这有助于我在编写查询时保持头脑清醒。您可能会或可能不会发现此约定有用。
推荐阅读
- neural-network - 引导式 Grad-CAM 可视化,梯度加权
- python - Django - UnboundLocalError
- java - Jolt 将带有数组的对象转换为单个数组
- ms-access - 将 MS 访问权限拆分到前端和后端,但后端位于另一台计算机中
- html - 如何将 css 应用于没有选择器的 HTML 项目
- php - 使用 curl 发送分块文件并接收
- hibernate - 为什么有时我的 CrudRepository 方法会抛出 java.lang.NullPointerException 而有时不会?
- java - 从休眠 4.3 迁移到休眠 5.1.16 有 QuerySyntaxException
- c++ - 有什么方法可以中止 cin 或 scanf
- networking - 两个路由器/防火墙无法ping通