Postgresql:如何在几次更新查询后验证约束?

时间:2018-05-22 09:44:39

标签: postgresql sql-update unique-constraint

我正在使用postgresql构建数据库。

enter image description here

我有3个表由多对多关系链接在一起。联接表uiComponent_cat_subcat使用subcategoryIdcategoryIdposition(图片中的红色)定义了一个唯一约束。

在我的工作流程中,我必须连续更新2个查询。第一个打破了约束,而第二个打破了约束。

我希望在 2次查询后​​验证此约束

ALTER TABLE "uiComponent_cat_subcat" ALTER CONSTRAINT "unique_constraint_categoryId_subcategoryId_position" DEFERRABLE INITIALLY DEFERRED;

我尝试在约束上使用DEFERRABLE属性,并将查询包装在一个事务中。但是,这只能应用于设置为外键的约束。

如何在进行两次更新查询后验证唯一约束?

编辑:以下是对象定义:

1 - 创建表

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 - 更新查询

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;

问题解决但我不知道为什么 在事务中包装查询是否允许我在提交后检查约束。

1 个答案:

答案 0 :(得分:0)

1 - 创建表

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 - 更新查询

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;

问题解决但我不知道为什么 在事务中包装查询是否允许我在提交后检查约束。