Postgresql 函数无法按预期使用 INSERT INTO

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

最佳答案

从给出的相当简约的描述(没有 PostgreSQL 版本,没有 CREATE FUNCTION 语句显示参数等,没有其他表结构,没有函数调用)我猜你正在尝试做一个合并,仅当行不存在时才插入行,如果行已存在则跳过行。

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

您需要使用循环在单个 BEGIN ... EXCEPTION block 中执行插入(慢)或 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在运行目标表之前对其进行锁定将确保它是安全的。

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

关于Postgresql 函数无法按预期使用 INSERT INTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17007929/

相关文章:

SQL Server唯一约束问题

postgresql - 错误 "password authentication failed for user "bucardo"at/usr/local/bin/bucardo line 308"while adding postgresql database in bucardo

java - 选择sha256解密和md5转换postgresql和java

java - Java 代码示例的 AWS RDS 快照

c++ - QSqlQuery 插入字符

php - mySQL:将值插入到具有外键关系的2个表中

sql - 如何对 Firebird 字段值施加不区分大小写的唯一约束?

java - 如何在Java中使特定参数唯一

postgresql - 为内置聚合函数创建别名

mysql - INSERT INTO 语法问题