I’m building a database with postgresql.
I have 3 tables linked together by a many to many relation. The join table uiComponent_cat_subcat
defines a unique constraint with subcategoryId
, categoryId
and position
(red on the picture).
In my workflow I must make 2 queries update in a row. The first one breaks the constraint whereas the second one sets it back.
I would like this constraint to be verified after the 2 queries.
ALTER TABLE "uiComponent_cat_subcat" ALTER CONSTRAINT "unique_constraint_categoryId_subcategoryId_position" DEFERRABLE INITIALLY DEFERRED;
I tried to use the DEFERRABLE
property on the constraint and to wrap my queries inside one transaction. However this can only be applied on constraints set to foreign keys.
How can I verify the unique constraint after the two update queries were made?
Edit: Here are the object definitions:
1 - CREATE TABLE
CREATE TABLE IF NOT EXISTS "uiComponent"
(
"id" uuid NOT NULL,
"name" varchar(255),
"preview" json,
"symbolID" varchar(255),
"libraryID" varchar(255),
"type" "public"."enum_uiComponent_type" DEFAULT 'basic',
"content" json,
"created_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
"updated_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "category"
(
"id" uuid NOT NULL,
"name" varchar(255),
"immuable" boolean,
"description" varchar(255),
"section" "public"."enum_category_section" NOT NULL DEFAULT 'Components',
"created_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
"updated_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "subcategory"
(
"id" uuid NOT NULL,
"name" varchar(255),
"position" integer NOT NULL,
"created_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
"updated_at" timestamp WITH time ZONE NOT NULL DEFAULT now(),
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "uiComponent_cat_subcat"
(
"id" uuid,
"uiComponentId" uuid NOT NULL REFERENCES "uiComponent" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
"categoryId" uuid NOT NULL REFERENCES "category" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
"subcategoryId" uuid REFERENCES "subcategory" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
"position" integer NOT NULL,
PRIMARY KEY ("id")
);
2 - CREATE CONSTRAINT
ALTER TABLE "uiComponent_cat_subcat"
ADD CONSTRAINT "unique_constraint_categoryId_subcategoryId_position" UNIQUE ("categoryId", "subcategoryId", "position")
DEFERRABLE INITIALLY DEFERRED;
3 - UPDATE QUERIES
START TRANSACTION;
UPDATE "uiComponent_cat_subcat"
SET "position"="position"+ 1
WHERE "position" BETWEEN 1 AND 1
AND "categoryId" = '10e4621e-f52d-4fe2-a408-139841718fd5'
AND "subcategoryId" = 'a7770326-35be-45ae-ba26-4635cfb6f4dc';
UPDATE "uiComponent_cat_subcat"
SET "position"=1
WHERE "id" = '50022f87-8fe9-4f21-a622-d5f51c16d9fc'
COMMIT;
The problem is solved but I don’t know why Does wrapping queries in a transaction allows me to check the constraint after the commit.