规则中的 PostgreSQL 9.5 UPSERT

PostgreSQL 9.5 UPSERT in rule

我在updatable视图系统中有一个INSERT规则,我想为此实现一个UPSERT,例如:

CREATE OR REPLACE RULE _insert AS
ON INSERT TO vue_pays_gex.bals
DO INSTEAD (
INSERT INTO geo_pays_gex.voie(name, code, district) VALUES (new.name, new.code, new.district)
ON CONFLICT DO NOTHING;

但是我认为这三列可以有很多不同的组合,我不认为我可以设置一个包含它们的约束(尽管我可能在 SQL 逻辑中缺少理解点), 因此使 ON CONFLIT DO NOTHING 部分无效。

理想的解决方案似乎是使用 EXCEPT,但它仅适用于 INSERT INTO SELECT 语句。有没有办法使用 INSERT INTO SELECT 语句引用新插入的行?像 FROM new.bals 这样的东西(在我的例子中)?

如果不是,我可以想象一个 WHERE NOT EXISTS 条件,但出现了与以前相同的问题。

我猜这是一个相当普遍的 SQL 需求,但找不到解决方法。有什么想法吗?

编辑:

根据要求,这里是 table 定义:

CREATE TABLE geo_pays_gex.voie
(
  id_voie serial NOT NULL,
  name character varying(50),
  code character varying(15),
  district character varying(50),
  CONSTRAINT prk_constraint_voie PRIMARY KEY (id_voie),
  CONSTRAINT voie_unique_key UNIQUE (name, code, district)
);

你如何定义独特性?如果是名称+代码+区的组合,那么只要在tablegeo_pays_gex.voie上加一个约束UNIQUE(name, code, district)即可。 3 一起必须是 unique... 但您可以多次使用相同的名称、代码或地区。

http://rextester.com/EWR73154

编辑 ***

由于您可以拥有空值并希望将它们视为唯一值,因此您可以通过替换空值的唯一索引来替换约束创建

CREATE UNIQUE INDEX
voie_uniq ON voie
(COALESCE(name,''), code, COALESCE(district,''));

除了@JGH的回答。

INSERT INSERT 的规则将导致无限递归(Postgres 9.6)。

完整 (不可)运行 示例:

CREATE SCHEMA ttest;

CREATE TABLE ttest.table_1 (
  id bigserial
    CONSTRAINT pk_table_1 PRIMARY KEY,
  col_1 text,
  col_2 text
);

CREATE OR REPLACE RULE table_1_always_upsert AS
ON INSERT TO ttest.table_1
DO INSTEAD (
  INSERT INTO ttest.table_1(id, col_1, col_2)
    VALUES (new.id, new.col_1, new.col_2)
  ON CONFLICT ON CONSTRAINT pk_table_1
    DO UPDATE
    SET col_1 = new.col_1,
      col_2 = new.col_2
);

INSERT INTO ttest.table_1(id, col_1, col_2)  -- will result error: infinity recursion in rules
  VALUES (1, 'One', 'A'),
         (2, 'Two', 'B');

INSERT INTO ttest.table_1(id, col_1, col_2)
  VALUES (1, 'One_updated', 'A_updated'),
         (2, 'Two_updated', 'B_updated'),
         (3, 'Three_inserted', 'C_inserted');

SELECT *
FROM ttest.table_1;