使用INSERT INTO,Postgresql函数无法正常工作

时间:2013-06-09 08:43:15

标签: postgresql insert unique-constraint

我有将数据从一个表插入另一个表的功能

   $BODY$
    BEGIN
            INSERT INTO backups.calls2 (uid,queue_id,connected,callerid2)
            SELECT distinct (c.uid) ,c.queue_id,c.connected,c.callerid2
            FROM public.calls c 
            WHERE c.connected is not null;
        RETURN;
    EXCEPTION WHEN unique_violation THEN NULL;
    END;
$BODY$

表的结构:

CREATE TABLE backups.nc_calls_id
(
  uid character(30) NOT NULL,
  queue_id integer,
  callerid2 text,
  connected timestamp without time zone,
  id serial NOT NULL,
  CONSTRAINT calls2_pkey PRIMARY KEY (uid)
 )
WITH (
  OIDS=FALSE
);

当我第一次执行此查询时,一切正常,已将200000行插入到具有唯一ID的新表中。 但是现在,当我再次执行它时,没有插入任何行

1 个答案:

答案 0 :(得分:3)

从给出的极简主义描述(没有PostgreSQL版本,没有CREATE FUNCTION语句显示params等,没有其他表结构,没有函数调用)我猜你正在尝试合并,你在哪里如果行已存在,则仅在跳过行时才插入行。

如果任何行已经存在,上述功能将跳过所有行。

您需要使用循环在单个BEGIN ... EXCEPTION块(慢)或LOCK表中执行插入并执行INSERT INTO ... SELECT ... FROM newtable WHERE NOT EXISTS (SELECT 1 FROM oldtable where oldtable.key = newtable.key)

INSERT INTO ... SELECT ... WHERE NOT EXISTS方法将执行得更好,但如果多个并发运行或者同时在目标表中插入任何其他内容,则会失败。 <{1}}在运行目标表之前会确保它是安全的。

PL / PgSQL循环LOCK方法听起来乍看起来很安全。然后你想想当你同时运行其中两个时会发生什么。首先插入一些键,首先插入其他键,这样它们之间就会有一个值的分割。没关系,他们一起构成全套。但是,如果只有其中一个提交而另一个因某些原因而失败呢?你将有一个有趣的稀疏插入结果。因此,如果使用这种方法,最好锁定目标表...在这种情况下,您也可以使用基于子查询的唯一性违规检查的更高效的单次传递BEGIN ... EXCEPTION