Что касается, on conflict
не распознает нарушения перечисления. Документация INSERT
гласит:
Необязательное условие ON CONFLICT
указывает альтернативное действие для вызова уникальной ошибки нарушения или нарушения ограничения исключения.
К сожалению, тип перечисления не попадает в эту категорию (то же самое относится к проверочным ограничениям, которые в противном случае могли бы быть здесь возможным решением).
Мы могли бы прибегнуть к хитрости перечисления значений перечисления с помощью enum_range()
, затем используя это в условном выражении:
insert into users(name, state)
select
name,
case when state = any(enum_range(null::us_state)::name[])
then state::us_state
end
from (values ('Bob', 'AA')) t(name, state)
Обратите внимание, что это создает значение NULL
, когда заданное значение не существует в перечислении, а не произвольная строка, такая как 'NULL'
; для меня это выглядит как правильный способ представления несопоставленных значений.
Демонстрация на DB Fiddle :
create type us_state as enum ('AL', 'WA');
create table users(name text, state us_state);
-- an attempt with "on conflict"
insert into users (name, state) values ('Bob', 'AA') on conflict(state) do nothing
-- ERROR: invalid input value for enum us_state: "AA";
-- LINE 1: insert into users (name, state) values ('Bob', 'AA') on conf...
-- new query
insert into users(name, state)
select
name,
case when state = any(enum_range(null::us_state)::name[])
then state::us_state
end
from (values ('Bob', 'AA'), ('Bill', 'AL')) t(name, state);
-- 2 rows affected
select * from users;
name | state
:--- | :----
Bob | <em>null</em>
Bill | AL