首页 > 解决方案 > 将 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');

但我认为这是不对的。有人可以帮我吗?

标签: oraclemerge

解决方案


您的合并语句快到了。我认为你追求的是更像这样的东西:

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';

从您的更新声明中。

然后只需根据需要更新或插入相关值即可。

注意我总是分别使用tgtsrc作为目标表和源表/子查询的别名;我发现这有助于我在编写查询时保持头脑清醒。您可能会或可能不会发现此约定有用。


推荐阅读