我有将数据从一个表插入另一个表的功能
$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的新表中。 但是现在,当我再次执行它时,没有插入任何行
答案 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
。