合并到postgres

时间:2018-09-25 11:46:07

标签: postgresql database-migration postgresql-9.5

我正在尝试将下面的oracle查询转换为postgres,

MERGE INTO table1 g
USING (SELECT distinct g.CDD , d.SGR
from  table2 g, table3 d
where g.IDF = d.IDF) f
ON (g.SGR = f.SGR and g.CDD = f.CDD)
   WHEN NOT MATCHED THEN
   INSERT (SGR, CDD)
   VALUES (f.SGR, f.CDD);

我做了以下与postgres兼容的更改:

WITH f AS (
SELECT distinct g.CDD , d.SGR
from  table2 g, table3 d
where g.IDF = d.IDF
),
upd AS (
update table1 g 
set 
SGR = f.SGR , CDD = f.CDD 
FROM f where g.SGR = f.SGR  and g.CDD = f.CDD  
returning g.CDD, g.SGR
)
INSERT INTO table1(SGR, CDD ) SELECT f.SGR, f.CDD FROM f;

但是令人怀疑的是,如果数据匹配,我的oracle查询不会更新任何列,但是无法相应地对其进行转换。有人可以帮我改正吗?

1 个答案:

答案 0 :(得分:3)

假设您在(sgr, cdd)上具有主键(或唯一键),则可以将其转换为insert ... on conflict语句:

insert into table1 (SGR, CDD)
select  distinct g.CDD, d.SGR
from table2 g
  join table3 d ON g.IDF = d.IDF
on conflict (cdd, sgr) do nothing;

如果您没有唯一的约束(这里有一个问题:为什么?),那么简单的INSERT ... SELECT语句应该可以工作(在Oracle中也可以工作)。

WITH f AS (
   SELECT distinct g.CDD, d.SGR
   from table2 g
     join table3 d on g.IDF = d.IDF
)
INSERT INTO table1 (SGR, CDD) 
SELECT f.SGR, f.CDD 
FROM f
WHERE NOT EXISTS (select *
                  from table1 t1
                     join f on (t1.sgr, t1.cdd) = (f.cdd, f.sgrf));

请注意,对于并发执行来说,这是安全的(Oracle的MERGE语句也不安全)。您仍然可以在表1中使用重复的值(关于(sgr,cdd)的组合)。

防止重复的唯一明智方法是创建唯一索引(或约束),这将使您能够使用效率更高的insert on conflict。您应该真的考虑一下,如果您的业务规则不允许重复。


请注意,我将WHERE子句中的古老的,隐式的联接转换为现代的,显式的JOIN运算符,但这不是必需的。