当我尝试在FROM语句中使用多个源时,我在Postgres 9.5中遇到ON CONFLICT DO UPDATE
的问题。
工作代码的示例:
INSERT INTO new.bookmonographs (citavi_id, abstract, createdon, edition, title, year)
SELECT "ID", "Abstract", "CreatedOn"::timestamp, "Edition", "Title", "Year"
FROM old."Reference"
WHERE old."Reference"."ReferenceType" = 'Book'
AND old."Reference"."Year" IS NOT NULL
AND old."Reference"."Title" IS NOT NULL
ON CONFLICT (citavi_id) DO UPDATE
SET (abstract, createdon, edition, title, year) = (excluded.abstract, excluded.createdon, excluded.edition, excluded.title, excluded.year)
;
错误代码:
INSERT INTO new.bookmonographs (citavi_id, abstract, createdon, edition, title, year)
SELECT "ID", "Abstract", "CreatedOn"::timestamp, "Edition", "Title", "Year"
FROM old."Reference", old."ReferenceAuthor"
WHERE old."Reference"."ReferenceType" = 'Book'
AND old."Reference"."Year" IS NOT NULL
AND old."Reference"."Title" IS NOT NULL
AND old."ReferenceAuthor"."ReferenceID" = old."Reference"."ID"
--Year, Title and Author must be present in the data, otherwise the entry is deemed useless, hence won't be included
ON CONFLICT (citavi_id) DO UPDATE
SET (abstract, createdon, edition, title, year) = (excluded.abstract, excluded.createdon, excluded.edition, excluded.title, excluded.year)
;
我在FROM语句中添加了一个额外的源,还有一个WHERE语句,以确保只有具有title,year和author的条目插入到新数据库中。 (如果旧的话。“引用”。“ID”存在于旧的中。“ReferenceAuthor”作为“ReferenceID”,然后作者存在。)即使没有附加的WHERE语句,查询也是错误的。我在SELECT中指定的列仅出现在old."Reference"
中,而不出现在old."ReferenceAuthor"
中。
目前old."ReferenceAuthor"
和old."Reference"
没有独特的约束,书籍专用的唯一限制是:
CONSTRAINT bookmonographs_pk PRIMARY KEY (bookmonographsid),
CONSTRAINT bookmonographs_bookseries FOREIGN KEY (bookseriesid)
REFERENCES new.bookseries (bookseriesid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT bookmonographs_citaviid_unique UNIQUE (citavi_id)
错误PSQL抛出:
错误:ON CONFLICT DO UPDATE命令不能再次影响行 提示:确保在同一命令中建议不插入的行具有重复的约束值。 **********错误**********
错误:ON CONFLICT DO UPDATE命令不能再次影响行 SQL状态:21000 提示:确保在同一命令中不建议插入的行具有重复的约束值。
我不知道什么是错的,或者为什么提示指向重复的约束值。
答案 0 :(得分:8)
问题是由于显然某些条目有多个作者。因此,您编写的select查询中的内部联接将返回同一条目的多个行,而INSERT ... ON CONFLICT
并不是这样。由于您只使用ReferenceAuthor
表进行过滤,因此您只需重写查询,以便它使用该表仅通过对相关的exists
过滤不具有任何作者的条目子查询。以下是:
INSERT INTO new.bookmonographs (citavi_id, abstract, createdon, edition, title, year)
SELECT "ID", "Abstract", "CreatedOn"::timestamp, "Edition", "Title", "Year"
FROM old."Reference"
WHERE old."Reference"."ReferenceType" = 'Book'
AND old."Reference"."Year" IS NOT NULL
AND old."Reference"."Title" IS NOT NULL
AND exists(SELECT FROM old."ReferenceAuthor" WHERE old."ReferenceAuthor"."ReferenceID" = old."Reference"."ID")
--Year, Title and Author must be present in the data, otherwise the entry is deemed useless, hence won't be included
ON CONFLICT (citavi_id) DO UPDATE
SET (abstract, createdon, edition, title, year) = (excluded.abstract, excluded.createdon, excluded.edition, excluded.title, excluded.year)
;
答案 1 :(得分:1)
使用显式INNER JOIN
将两个源表连接在一起:
INSERT INTO new.bookmonographs (citavi_id, abstract, createdon, edition, title, year)
SELECT "ID", "Abstract", "CreatedOn"::timestamp, "Edition", "Title", "Year"
FROM old."Reference"
INNER JOIN old."ReferenceAuthor" -- explicit join
ON old."ReferenceAuthor"."ReferenceID" = old."Reference"."ID" -- ON condition
WHERE old."Reference"."ReferenceType" = 'Book' AND
old."Reference"."Year" IS NOT NULL AND
old."Reference"."Title" IS NOT NULL
ON CONFLICT (citavi_id) DO UPDATE
SET (abstract, createdon, edition, title, year) =
(excluded.abstract, excluded.createdon, excluded.edition, excluded.title,
excluded.year)