Элегантное решение проблемы увеличения инкремента при вставке дубликатов.
Множество раз в различных форумах всплывает вопрос: Как избежать увеличения автоинкремента при вставке дубликатов в таблицу?
Хотя я сам на тех же форумах отвечал что это не критично и не стоит из-за этого волноваться, а если волнуетесь то используйте bigserial
и тогда точно хватит! Но душа тем не менее требовала гармонии. И так классика:
create table tbl (
id serial,
val text,
primary key (id),
unique (val)
);
-- Вставляем Раз и Два
insert into tbl (val) values ('One'), ('Two');
-- Попробуем так
insert into tbl (val) values ('One'), ('Three') on conflict (val) do nothing;
select * from tbl;
+====+=======+
| id | val |
+====+=======+
| 1 | One |
| 2 | Two |
| 4 | Three |
+----+-------+
Видно, автоинкремент растет даже если мы используем UPSERT
Конечно есть вариант с проверкой NOT EXISTS
, но это не для слабонервных:
insert into target2 (val)
select val from source
where not exists (select true from target2 where target2.val = source.val);
И вот наконец то в PostgreSQL 15 завозят оператор MERGE
:
merge into target3 t
using source s on t.val = s.val
when not matched then insert (val) values (val);
здесь читаем про Применение оператора MERGE в PostgreSQL