Pull to refresh

Элегантное решение проблемы увеличения инкремента при вставке дубликатов.

Множество раз в различных форумах всплывает вопрос: Как избежать увеличения автоинкремента при вставке дубликатов в таблицу?

Хотя я сам на тех же форумах отвечал что это не критично и не стоит из-за этого волноваться, а если волнуетесь то используйте 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);

здесь тестируем SQL запросы

здесь читаем про Применение оператора MERGE в PostgreSQL

Total votes 8: ↑8 and ↓0+10
Comments0

Articles