0

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

   $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 的新表中。但是现在,当我再次执行它时,没有插入任何行

4

1 回答 1

3

从给出的相当简约的描述(没有 PostgreSQL 版本,没有CREATE FUNCTION显示参数等的语句,没有其他表结构,没有函数调用)我猜你正在尝试进行合并,只有在它没有的情况下才插入一行' t 通过跳过已经存在的行来存在。

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

您需要使用循环在单个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方法的性能会好很多,但如果同时运行多个或其他任何内容同时插入目标表,则会失败。LOCK在运行它之前 ing 目标表将确保它是安全的。

乍一看,PL/PgSQL 循环BEGIN ... EXCEPTION方法听起来不错且安全。然后你想想当你同时运行其中两个时会发生什么。一个会先插入一些键,一个会先插入其他键,因此它们之间的值是分开的。没关系,他们一起组成了全套。但是,如果其中只有一个提交而另一个由于某种原因失败了怎么办?您将得到一个有趣的稀疏插入结果。出于这个原因,如果也使用这种方法,最好锁定目标表......在这种情况下,您不妨使用效率更高的单通道INSERT和基于子查询的唯一性违规检查。

于 2013-06-09T08:54:14.183 回答