【问题标题】:Postgres sql exception handling for batch insert批量插入的 Postgresql 异常处理
【发布时间】:2015-09-29 17:54:15
【问题描述】:

我有两张表,我正在将数据从一张表插入到另一张表中。

insert into a (id1, value1)
select id, value from b

id1 是唯一的,当我在表 b 中有重复的 id 时。如何在不停止执行的情况下捕获 PostgreSQL 中每一行的异常。

【问题讨论】:

  • 对于给定的 id,表 b 中 id 的值是否不同?
  • 是的。价值观不同
  • 那么你所说的例外是什么意思?您可以插入具有相同 id 的不同值。如果您只需要一个值,则需要指定一个条件。

标签: sql postgresql exception stored-procedures


【解决方案1】:

如果您不能按照@a_horse_with_no_name 的建议进行操作并避免异常,那么可以使用循环查询并执行BEGIN ... EXCEPTION ... 块的PL/PgSQL 过程。

大量比使用WHERE 子句和(如果需要)连接过滤出问题行效率低,因此应尽可能避免。

必要的主要时间是,如果验证代码抛出异常,您无法运行以生成 where 子句的布尔值。不幸的是,大多数 PostgreSQL 的数据类型输入函数都没有“测试”模式,在这种模式下,您可以获得 NULL 结果或无效输入的错误标志,因此通常是日期/时间解析等情况。

你想做这样的事情:

DO
LANGUAGE plpgsql
$$
DECLARE
  r record;
BEGIN
  FOR r IN SELECT a, b FROM mytable
  LOOP
    BEGIN
      INSERT INTO newtable (x, y)
      VALUES (r.a, r.b);
    EXCEPTION
      WHEN check_violation THEN
        RAISE NOTICE 'Skipped row %', r.a;
    END;
  END LOOP;
END;
$$;

有关详细信息,请参阅 PL/PgSQL 手册。

请注意,这会为每个循环迭代执行一个子事务,并且还需要为每个迭代设置执行器状态,因此它方式比使用INSERT INTO ... SELECT ... WHERE ... 慢。

【讨论】:

  • 但它在第一次异常时中断并且不会继续循环。
【解决方案2】:

只是不要插入那些会导致错误的内容:

insert into a (id1, value1)
select id, value 
from b
where not exists (select 1
                  from a
                  where a.id1 = b.id);

如果 a 为空,则只选择唯一的:

insert into a (id1, value1)
select distinct on (id) id, value 
from b
order by id;

【讨论】:

    猜你喜欢
    • 2012-07-03
    • 2014-05-05
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2020-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多