在违反约束的情况下使用 INSERT INTO for POSTGRESQL 迁移数据

Migrate data with INSERT INTO for POSTGRESQL with constraints violated

假设我有两个 table,oldstatistics 和 statistics,较新的 table 对时间列有不同的约束。

例如,较新的 table 有以下限制,而旧的 table 有违反的数据:

CONSTRAINT check_ts_2013_03 CHECK (statistictime >= '2013-03-01 01:00:00+01'::timestamp with time zone AND statistictime < '2013-04-01 02:00:00+02'::timestamp with time zone)

和违反的数据假设他们有统计时间 '2013-04-01 00:15:00+01'

我用 INSERT OR IGNORE 为 SQLite 找到了一些解决方案(如果发生约束冲突,将跳过这些行,并且它将继续),但不适用于 POSTGRESQL。

你有什么建议吗?

你想用这些数据做什么,想合并它们吗?

  • 为了同时使用这两个表,我建议使用视图。
  • 如果想在不修改数据的情况下将oldStatisticTime插入statisticTime,可以解除对触发器的约束,不触发触发器,插入数据,然后开启触发器。

您可以使用 plpgsql 函数和异常块(请参阅 documentation)执行此操作:

CREATE or REPLACE FUNCTION insert_or_ignore() RETURNS VOID AS $$
DECLARE _value timestamp;

BEGIN
  FOR _value IN SELECT statistictime FROM oldstatistics LOOP   
    BEGIN
      INSERT INTO statistics(statistictime) VALUES (_value);
    EXCEPTION when check_violation THEN
       -- DO NOTHING
    END;
  END LOOP;
END;
$$
LANGUAGE plpgsql;

-- run the function
SELECT insert_or_ignore();

您可能还需要插入其他列,而不仅仅是 statistictime。在这种情况下,您必须在 DECLARE 块中声明它们。 您也可以使用 DO 语句来做同样的事情,而无需先创建函数(参见 documentation:

DO $$
DECLARE _value timestamp;    
BEGIN
      FOR _value IN SELECT statistictime FROM oldstatistics LOOP   
        BEGIN
          INSERT INTO statistics(statistictime) VALUES (_value);
        EXCEPTION when check_violation THEN
           -- DO NOTHING
        END;
      END LOOP;
END$$;

我在这里捕获了 "check_violation" 异常,但也检查了所有 PostgreSQL 错误代码,如果您想捕获其他类型的错误:error codes