Итерация над переменной и вставка дополнительных строк Postgres

Просто хочу отметить, да, я видел подобные вопросы здесь, но ни один не был достаточно близким для данного конкретного вопроса.

У меня есть таблица (назовем ее 'table 1') в postgres с тремя колонками, основанными на модели django, 'ID' (автоматически увеличивающееся значение), 'affiliation' и 'entry'.

Мне нужно взять каждую запись, где affiliation = 52, а затем добавить дополнительную строку с entry = query.entry и affiliation = 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; $$

Есть идеи? Я в полной растерянности... Это, безусловно, самый сложный запрос, который я когда-либо выполнял.

Для этого не нужен (неуклюжий, неэффективный и неправильный) цикл.

Для начала у вас должно быть ограничение UNIQUE на (affiliation, entry).

С 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.

Вернуться на верх