【问题标题】:INSERT unique rows taken from the same table with a changed columnINSERT 从同一个表中取出的唯一行,但列已更改
【发布时间】:2021-11-01 08:42:43
【问题描述】:

我在 Postgres 中有一个表 table_1,其中包含基于 Django 模型的三列,ID(自动递增值)、affiliationentry

我需要做的是获取affiliation = 52 所在的每个条目,然后添加带有entry = query.entryaffiliation = 48 的附加行。我需要额外的行,而不是更改值。我还需要确保 entry + affiliation 对不存在。

我最近的尝试:

do $$
declare
id_array int[];
begin
insert into id_array table_1.entry where table_1.affiliation = 52;
for id in id_array
loop
if not exists (select entry from table_1 where affiliation = 48)
then 
insert into table_1 (affiliation, entry) values (48, id);
else
raise notice "already exists";
end if;
endloop;
end; $$

我仍然遇到语法错误!有任何想法吗?我完全不知所措。这是迄今为止我尝试过的最复杂的查询。

【问题讨论】:

  • 将语法错误添加到您的问题中。虽然我要说问题就在这里:insert into id_array ...。如果我没听错,那可能应该是:select into id_array array_agg(entry) from table1 where affiliation = 52;

标签: sql django postgresql unique-constraint upsert


【解决方案1】:

为此,您不需要一个(笨拙、低效且不正确的)循环。

您应该首先对(affiliation, entry) 有一个UNIQUE 约束。

带有UNIQUE索引

使用UNIQUE 约束或(affiliation, entry) 上的索引只需使用“UPSERT”:

INSERT INTO table_1 (affiliation, entry)
SELECT 48, entry
FROM   table_1
WHERE  affiliation = 52
ON     CONFLICT DO NOTHING;

ON CONFLICT DO NOTHING 跳过任何可能重复的内容。任务完成。

这对于并发写入负载下的竞争条件是安全的。 见:

没有UNIQUE索引

SELECT DISTINCT 48, t1.entry
FROM   table_1 t1
LEFT   JOIN table_1 t2 ON t2.entry = t1.entry
                      AND t2.affiliation = 48
WHERE  t1.affiliation = 52
AND    t2.entry IS NULL;  -- does not exist yet

我添加了DISTINCT,因为没有提到UNIQUE 索引,(affiliation, entry) 上可能有重复,我们不想要多个副本。

在并发写入负载下对竞争条件不安全。

见:

两个查询都假定 entry 被定义为 NOT NULL。否则,您需要定义如何处理 NULL 值。

【讨论】:

    猜你喜欢
    • 2021-06-23
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多