Reputation: 174
I'm trying to convert an oracle Merge
statement to postgreSQL(>9.5).
Unfortunately postgres(=<11) still doesn't support MERGE
and the best alternative method I found was the INSERT ... ON CONFLICT
also called UPSERT
.
I was able to convert the more basic merge statement into upserts but for more complex queries I need to access columns from the source query the are not inserted but only used for logic in the DO UPDATE
.
Unfortunately the special excluded.
-table uses the same column identifiers as the target.
ORACLE MERGE version
MERGE INTO tgt
USING (SELECT nam.text AS normalizedtext, norm.originaltext,
norm.entryid AS entryID,
nam.name_id AS name_id,
norm.islink AS islink
FROM norm, nam
WHERE norm.name_id = nam.name_id
GROUP BY originaltext
) source
ON (tgt.languagecode = :langCode AND tgt.text = source.originaltext)
WHEN MATCHED AND ptid IS NULL THEN
UPDATE SET tgt.name_id = source.name_id,
tgt.PTID = source.entryID,
tgt.normname = CASE WHEN source.islink = 1 THEN
source.originaltext ELSE source.normalizedtext END CASE
Current postgress version
INSERT INTO tgt (text, normname, ptid, name_id, languagecode)
SELECT nam.text AS normalizedtext, norm.originaltext,
norm.entryid AS entryID,
nam.name_id AS name_id,
:langCode, -- edited
norm.islink AS islink
FROM norm, nam
WHERE norm.name_id = nam.name_id
GROUP BY originaltext
ON CONFLICT (text, languagecode)
DO UPDATE
SET name_id = excluded.name_id,
ptid = excluded.ptid,
normname = CASE WHEN excluded.islink = 1 THEN -- PROBLEM
excluded.originaltext ELSE excluded.normalizedtext END -- PROBLEM
WHERE ptid IS NULL;
The problem is that the excluded table does not contain the columns: isLink
, originaltext
and normalizedtext
.
ERROR: column excluded.islink does not exist
Is there any workaround or how can u use the source columns in the update query? If this is not possible, is there an other alternative to write merge statements in postgres?
Upvotes: 2
Views: 750
Reputation:
You can move that CASE expression to the SELECT statement:
INSERT INTO tgt (text, normname, ptid, name_id, languagecode)
SELECT nam.text,
case islink
when 1 then norm.originaltext
else normalizedtext
end as normname,
norm.entryid AS ptid,
nam.name_id AS name_id,
:langCode as languagecode
FROM norm
JOIN nam ON norm.name_id = nam.name_id
GROUP BY originaltext
ON CONFLICT (text, languagecode)
DO UPDATE
SET name_id = excluded.name_id,
ptid = excluded.ptid,
normname = excluded.normname
WHERE ptid IS NULL;
Upvotes: 1