Измените значение вставки, если значение не в ENUM - PullRequest
3 голосов
/ 13 марта 2020

Я хочу вставить значение в Postgres

Если у меня есть тип enum в таблице и я хочу изменить входное значение, которого нет в списке enum

как

create type us_state as enum ('AL', ..., 'NULL');

insert into user (name, state)
values ('Bob', 'AA')
conflict on state is not valid us_state update value = 'NULL'

как использовать условную вставку или обновить значение при вставке?

1 Ответ

2 голосов
/ 13 марта 2020

Что касается, 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   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...