问题
Am trying to convert below oracle query to 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);
I made changes as below compatible to 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;
But am doubtful ,my oracle query is not updating any columns if data matched , but am unable to convert it accordingly . Can anyone help me to correct it ?
回答1:
Assuming you have a primary (or unique) key on (sgr, cdd)
you can convert this to an insert ... on conflict
statement:
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;
If you don't have a unique constraint (which bears the question: why?) then a straight-forward INSERT ... SELECT statement should work (which would have worke in Oracle as well).
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));
Note that this is NOT safe for concurrent execution (and neither is Oracle's MERGE statement). You can still wind up with duplicate values in table1 (with regards to the combination of (sgr,cdd)
).
The only sensible way to prevent duplicates is to create a unique index (or constraint) - which would enable you to use the much more efficient insert on conflict
. You should really consider that if your business rules disallow duplicates.
Note that I converted your ancient, implicit join in the WHERE clause to a modern, explicit JOIN
operator, but it is not required for this to work.
来源:https://stackoverflow.com/questions/52497478/merge-in-postgres