【发布时间】:2019-09-07 09:30:53
【问题描述】:
我正在尝试将 oracle Merge 语句转换为 postgreSQL(>9.5)。
不幸的是,postgres(=MERGE,我发现最好的替代方法是INSERT ... ON CONFLICT,也称为UPSERT。
我能够将更基本的合并语句转换为 upsert,但对于更复杂的查询,我需要访问源查询中的列,这些列未插入,但仅用于 DO UPDATE 中的逻辑。
不幸的是,特殊的excluded.-table 使用与目标相同的列标识符。
ORACLE MERGE 版本
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
当前 postgress 版本
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;
问题是排除的表不包含列:isLink、originaltext 和 normalizedtext。
错误:列被排除。islink 不存在
是否有任何解决方法或如何在更新查询中使用源列? 如果这不可能,是否有其他替代方法可以在 postgres 中编写合并语句?
【问题讨论】:
-
norm.islink的值在插入过程中被放入列languagecode- 开始时看起来是错误的。但如果这确实是正确的,您需要使用目标的表列:CASE WHEN excluded.languagecode = 1 THEN ... -
是的,谢谢,我刚刚注意到我忘记了 SELECT 中的
languagecode。但如果没有匹配项,我不希望插入该值。我可以使用一个虚拟列名,也许那没有连接到 tgt 表 -
现在您的 select 语句包含更多您拥有 INSERT 目标列的列 - 即使没有 ON CONFLICT,这也不起作用。
标签: oracle postgresql merge upsert