@ErwinBrandstetter спасибо - На самом деле я отвечал не на тот вопрос :)

ьзуя Postgres 9.6, я следовал стратегии, рекомендованной вhttps://stackoverflow.com/a/40325406/435563 сделатьINSERT или жеSELECT и вернуть полученный идентификатор:

with ins as (
  insert into prop (prop_type, norm, hash, symbols)
  values (
    $1, $2, $3, $4
  ) on conflict (hash) do
    update set prop_type = 'jargon' where false
  returning id)
select id from ins
union all
select id from prop where hash = $3

Однако иногда это ничего не возвращает. Я бы ожидал, что он вернет строку, несмотря ни на что. Как я могу это исправить, чтобы он всегда возвращал идентификатор?

Примечание: несмотря на то, что строка не возвращена, строка, кажется, существует при проверке. Я полагаю, что проблема может быть связана с попыткой добавить одну и ту же запись через две сессии одновременно.

Данная таблица определяется как:

create table prop (
  id serial primary key,
  prop_type text not null references prop_type(name),
  norm text not null,
  hash text not null unique,
  symbols jsonb
);

Данные:

EDT DETAIL:  parameters: $1 = 'jargon', $2 = 'j2', $3 = 'lXWkZSmoSE0mZ+n4xpWB', $4 = '[]'

Если я изменюprop_type = 'jargon' вprop_type = 'foo' оно работает! Казалось бы, блокировка не взята, если выражение ничего не изменит, даже еслиwhere false пункт. Должно ли это зависеть от того, как я угадал значение, которого не было бы в строке? Или есть лучший способ убедиться, что вы получите блокировку?

---ОБНОВИТЬ ---

Общая ситуация заключается в том, что приложение пыталось сохранить ориентированный ациклический граф, используя пул соединений (... с автоматической фиксацией), и использовало этот запрос для получения идентификатора, исключая дубликаты. [Оказывается, гораздо разумнее использовать транзакцию и просто сериализовать одно соединение. Но поведение, когда есть спор здесь, странное.]

Ограничение внешнего ключа, кажется, не влияет на вставку - например:

create table foo(i int unique, prop_id int references prop(id));
insert into foo values (1, 208);
insert into foo values (1, 208) 
on conflict (i) do update set prop_id = 208 where false;
--> INSERT 0 0
insert into foo values (1, 208) 
on conflict (i) do update set prop_id = -208 where false;
--> INSERT 0 0

Обратите внимание, один с действительным FK 208, другой с недействительным -208. Если я подключу выбор к любому из них с полным шаблоном, то в ситуациях без конфликтов они оба возвращают i = 1, как и ожидалось.

Ответы на вопрос(2)

Ваш ответ на вопрос