Допустим, у меня есть простая таблица в Postgres 9.5:
CREATE TABLE "public"."outcomes" (
"id" serial,
"ordinal" int NOT NULL,
"outcome" varchar,
PRIMARY KEY ("id")
);
Мне нужно поддерживать произвольный порядок, определенный ordinal
. Мне нужно иметь возможность вставить строку между другими строками, как определено их порядковым номером.
У меня есть некоторые основные данные в таблице:
INSERT INTO "public"."outcomes"("ordinal", "outcome") VALUES('1', 'foo');
INSERT INTO "public"."outcomes"("ordinal", "outcome") VALUES('2', 'bar');
INSERT INTO "public"."outcomes"("ordinal", "outcome") VALUES('3', 'baz');
Я хочу иметь возможность запускать это:
INSERT INTO "public"."outcomes"("ordinal", "outcome") VALUES('2', 'glorb');
и иметь строки «bar» и «baz» автоматически увеличивающие свой порядковый номер.
Я дошел до добавления отложенного уникального ограничения:
ALTER TABLE outcomes
ADD CONSTRAINT outcomes_ordinal_key
UNIQUE (ordinal) DEFERRABLE INITIALLY IMMEDIATE
и попытался вставить таким образом:
INSERT INTO outcomes("ordinal", "outcome")
VALUES('2', 'glorb')
ON CONFLICT (ordinal)
DO UPDATE SET "ordinal" = "outcomes"."ordinal" + 1 WHERE "outcomes"."ordinal" >= EXCLUDED.ordinal;
но это дает эту ошибку:
ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters
а если ограничение не является отложенным, оно немедленно терпит неудачу, потому что при попытке обновить порядковый номер bar
s с 2 на 3 возникает конфликт с порядковым номером baz
.
Как я могу сделать это с помощью Postgres?
row_number()
, и определить свой заказ, используя другие данные. Однако требование произвольности порядка останавливает вас от использования этого подхода. TBH, я бы пересмотрел ваши требования - расскажите нам о вашей реальной проблеме, а не о том, где вы падаете с предложенным вами решением а>. - person Ben   schedule 30.05.2016row_number() over (order by <datetime_column> desc nulls last, <pk> desc)
- вы можете указать два порядка, и, поскольку вы используете ПК только тогда, когда нет даты, это должно работать - вы также получаете разрешение на конфликт в случае, когда два пользователя вставляют строки точно в в то же время. - person Ben   schedule 30.05.2016(A+B)/2.0
. - person Daniel Vérité   schedule 31.05.2016