Let's say I have a simple table in Postgres 9.5:
CREATE TABLE "public"."outcomes" (
"id" serial,
"ordinal" int NOT NULL,
"outcome" varchar,
PRIMARY KEY ("id")
);
I need to maintain an arbitrary order, as defined by ordinal
. I need to be able to insert a row in between other rows, as defined by their ordinal.
I've got some basic data in the table:
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');
I want to be able to run this:
INSERT INTO "public"."outcomes"("ordinal", "outcome") VALUES('2', 'glorb');
and have the 'bar' and 'baz' rows automatically increment their ordinal.
I got as far as adding a deferrable unique constraint:
ALTER TABLE outcomes
ADD CONSTRAINT outcomes_ordinal_key
UNIQUE (ordinal) DEFERRABLE INITIALLY IMMEDIATE
and tried to insert thusly:
INSERT INTO outcomes("ordinal", "outcome")
VALUES('2', 'glorb')
ON CONFLICT (ordinal)
DO UPDATE SET "ordinal" = "outcomes"."ordinal" + 1 WHERE "outcomes"."ordinal" >= EXCLUDED.ordinal;
but that yields this error:
ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters
and if the constraint is not deferrable, it immediately fails because when it tries to update bar
s ordinal from 2 to 3, it conflicts with baz
's ordinal.
How can I accomplish this with Postgres?