PostgreSQL - 继续使用unique_violation(plpgsql)

met*_*ras 9 postgresql plpgsql

我有一个PostgreSQL表,其中有一些索引的字段,并且必须是唯一的,以防止重复.这是由于PLPGSQL函数插入所有字段并捕获unique_violation异常,即使只有一个重复,它也会停止插入记录.

由于性能问题我不能做几个INSERT(其中一些是以数百个完成的),问题是它会停止所有进程,即使只有一个重复,就像下面示例中最火的两个值一样.

CREATE OR REPLACE FUNCTION easy_import() RETURNS VOID AS
  $$
  BEGIN
    BEGIN
      INSERT INTO things ("title", "uniq1", "uniq2") VALUES
      ('title 1', 100, 102),
      ('title 2', 100, 102),
      ('title 3', 101, 102),
      ('title 4', 102, 102),
      ('title 5', 103, 102),
      ('title 6', 104, 102),
      ('title 7', 105, 102),
      ('title 8', 106, 102),
      ('title 9', 107, 102),
      ('title 10', 108, 102);
      RETURN;
    EXCEPTION WHEN unique_violation THEN
      -- do nothing
    END;
  END;
  $$
  LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

有没有办法忽略一个记录的unique_violation并阻止它停止进一步的INSERT?

谢谢.

更新

  • 唯一索引在"uniq1"和"uniq2"字段中有它,我很抱歉这个混乱.
  • 虽然@ cdhowie的解决方案似乎是最好的,但它忽略了这样一个事实:如果你运行相同的查询,它将触发错误.这很奇怪,因为查询是JOIN有原因的.仍在努力.

cdh*_*wie 6

假设唯一约束是在uniq1和uniq2周围复合的,这将起作用:

INSERT INTO things

WITH new_rows (title, uniq1, uniq2) AS (VALUES
    ('title 1', 100, 102),
    ('title 2', 100, 102),
    ('title 3', 101, 102),
    ('title 4', 102, 102),
    ('title 5', 103, 102),
    ('title 6', 104, 102),
    ('title 7', 105, 102),
    ('title 8', 106, 102),
    ('title 9', 107, 102),
    ('title 10', 108, 102)
)

SELECT
    DISTINCT ON (n.uniq1, n.uniq2)
    n.title, n.uniq1, n.uniq2

FROM new_rows AS n

LEFT JOIN things AS t
ON n.uniq1 = t.uniq1 AND n.uniq2 = t.uniq2

WHERE t.uniq1 IS NULL;
Run Code Online (Sandbox Code Playgroud)

实际上,这可能比单个INSERT语句的性能更差,但它是唯一能够解决问题的其他事情.对每种方法进行基准测试,看看哪种方法最适合您.