【问题标题】:Skip Unique key violations for INSERTing all records which are ok跳过唯一键违规以插入所有正常的记录
【发布时间】:2020-12-23 23:37:47
【问题描述】:

在 Postgres 表中,我还有一个主键(Auto gen)和一个唯一约束。

目前:在使用 SELECT 语句进行 INSERTING 时,如果违反了重复(唯一约束),则它根本不会 INSERT 任何内容。

要求:如果发生任何重复,它应该跳过那些记录,在临时表中捕获它们,并继续插入所有正常的记录(没有约束问题)

表结构:

CREATE TABLE invoice_output (
    id SERIAL,
    title TEXT UNIQUE NOT NULL,
    description TEXT NOT NULL,
    CONSTRAINT Invoice_pk PRIMARY KEY(id),
    CONSTRAINT title_unique UNIQUE(title)
);

如下调用函数进行插入:

CREATE OR REPLACE FUNCTION public.fn_create_invoice_output(<params>)
 RETURNS integer
 LANGUAGE plpgsql
AS $function$
...

BEGIN
  INSERT INTO public.invoice_output(id,title,description)
  SELECT id,title,description FROM public.invoice_input;

    IF NOT FOUND THEN
      RAISE WARNING  'fn_create_invoice_header_output() - job id or client not found';
      status := -1;
    END IF;

   RETURN status;

END;

$function$
;

我收到 SQL 错误 [23505]:错误:重复键值违反唯一约束。

我怎样才能创建一个例外,以便只插入和提交非重复项。并且重复的键可以从插入中跳过,捕获并打印出来

我在插入语句之后尝试过这个

EXCEPTION WHEN unique_violation THEN RAISE NOTICE 'row skipped in  public.fn_create_invoice_output ';

或者我们可以迭代插入命令的select语句的结果集,然后很容易做到吗?

【问题讨论】:

标签: postgresql


【解决方案1】:

您可以将 CONFLICT 子句用作:

INSERT INTO public.invoice_output (id, title, description)
    SELECT id, title, description FROM public.invoice_input
    ON CONFLICT (id) DO NOTHING;

参考:https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT

【讨论】:

    【解决方案2】:

    你可以使用ON CONFLICT:

    INSERT INTO public.invoice_output (id,title,description)
    SELECT id,title,description 
    FROM public.invoice_input
    ON CONFLICT DO NOTHING;
    

    【讨论】:

    • 不幸的是,ON CONFLICT 仅限于跳过行(没有指示这样做)或更新当前值(也没有指示这样做),但您不能“捕获并打印出来”或根据需要记录。为此,您可以通过仅选择已经存在的行来迭代游标并捕获每个异常或抢先记录现有行。然后修改 insert-select 以仅获取不存在的行。无论哪种方式,您都需要为登录性能付费。你的问题:值得付出代价吗?如果不只是坚持冲突,什么也不做。
    猜你喜欢
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2011-05-20
    相关资源
    最近更新 更多