依赖于多个表的 SQL 约束

标签 sql postgresql

一旦我有了一个简单的数据库:

CREATE TABLE workpiece
(
  id serial primary key
  -- More columns, not important here
);

CREATE TABLE workequipment
(
  id serial primary key
  -- More columns, not important here
);

CREATE TABLE workpiece_workequipment
(
  workpiece_id integer not null references workpiece(id),
  workequipment_id integer not null references workequipment(id),
  primary key(workpiece_id, workequipment_id)
);

但是现在要求改变了:我必须包括 工作设备(如工具、量具等)以及 并强制每个工件不能多次使用相同类型的工作设备。

所以我想到了以下内容:

CREATE TABLE workpiece
(
  id serial primary key
  -- More columns, not important here
);

CREATE TABLE workequipment
(
  id serial primary key,
  equipment_type integer, -- An enum in real world
  -- More columns, not important here
  unique(id, equipment_type)
);

CREATE TABLE workpiece_workequipment
(
  workpiece_id integer not null references workpiece(id),
  workequipment_id integer not null,
  workequipment_type integer not null,
  primary key(workpiece_id, workequipment_id),
  foreign key(workequipment_id, workequipment_type) references workequipment(id, equipment_type),
  unique(workpiece_id, workequipment_type)
);

可以使用这种冗余来强制约束吗? 如果是,我应该删除表 workequipment 中的 unique(id, equipment_type) 并将 (id, equipment_type) 设为主键? 或者有更好的解决方案吗?

最佳答案

为此你需要功能唯一索引:

CREATE TABLE workpiece
(
  id serial primary key
  -- More columns, not important here
);

CREATE TABLE workequipment
(
  id serial primary key,
  equipment_type integer
  -- More columns, not important here
);

CREATE TABLE workpiece_workequipment
(
  workpiece_id integer not null references workpiece(id),
  workequipment_id integer not null references workequipment(id),
  primary key(workpiece_id, workequipment_id)
);

-- Magic starts here :)

create function get_workequipment_type(int) returns int immutable language sql as $$
  select equipment_type from workequipment where id = $1
$$;

create unique index idx_check_wetype_unique
  on workpiece_workequipment(workpiece_id, get_workequipment_type(workequipment_id));

测试:

insert into workpiece values(default);
insert into workequipment(equipment_type) values(1),(1),(2);
insert into workpiece_workequipment values(1,1),(1,3); -- Works
--insert into workpiece_workequipment values(1,1),(1,2); -- Fails

关于依赖于多个表的 SQL 约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48165005/

相关文章:

MySQL : How to update a table field to a value fetched from another table

linux - 须藤: psql: command not found: can't fix it

c - Postgresql 自定义 C 聚合函数抛出段错误

mysql - 删除带左连接的数据表

sql - MySQL 1064 语法错误

MySQL检查表是否只包含这种特定类型

python - 测试 Postgres-DB 的连接

python - 无法在使用 Python 3.4.3 和 PostgreSQL 9.4.4 的 Windows 7 上安装 psycopg

java - 在 Java 8 中使用 Hibernate 5+ 的 PostgreSQL 9.6 DATE 列映射

mysql - 在 select 子句中分配和使用 mysql 用户变量