使用外来列的唯一多列密钥

时间:2012-11-19 23:34:03

标签: mysql unique-constraint

假设我有以下表,这些表实现了部件和对象之间的多对多关系,其中链接表具有唯一的密钥对(object_id,part_id),因此没有重复的行:

部分表:

part_id | part_name | part_zone
--------+-----------+----------  
0       | part1.0   | top  
1       | part2     | bottom  
2       | part1.1   | top
3       | part3     | top

对象表:

object_id | object_name
----  ----+-----------
0         | object1
1         | object2
2         | object3
3         | object4

链接表:

object_id | part_id
------  --+---------
0         | 0
0         | 1
1         | 1
1         | 2

还有一个限制因素是对象中每个part_zone应该只有一个。因此,如果要将part_zone列移动到链接表并将键更改为唯一对(object_id,part_zone),那么这将得到满足。我不想这样做,因为part_zone应该在part表中。在我的脑海中,我希望保持表格不变,但使用(object_id,part_zone)唯一键,其中part_zone通过part_id上的连接从部分表中提取。

希望我的意图很明确,但我不太确定这是最好的实施方式,或者我正在使用正确的术语来表达我所追求的目标。

提前感谢能够提供任何见解的任何人。

1 个答案:

答案 0 :(得分:0)

您可以将part_zone添加到Link,并在(part_zone, part_id)表中引用Part的级联复合外键约束;这样,您可以按照建议在UNIQUE上定义(object_id, part_zone)约束,同时仍然可以从part_zone表维护Part

ALTER TABLE Link ADD part_zone varchar(10);  -- should be same size as in Part
ALTER TABLE Part ADD INDEX (part_zone, part_id);

UPDATE Link JOIN Part USING (part_id) SET Link.part_zone = Part.part_zone;

ALTER TABLE Link
  ADD FOREIGN KEY (part_zone, part_id) REFERENCES Part (part_zone, part_id)
    ON UPDATE CASCADE,
  ADD UNIQUE INDEX (object_id, part_zone)
;

您甚至可以在INSERTUPDATE上定义触发器,以填充Link中的值,以便您无需手动执行:

CREATE TRIGGER link_insert BEFORE INSERT ON Link FOR EACH ROW
  SET NEW.part_zone = (SELECT part_zone FROM Part WHERE part_id = NEW.part_id);

CREATE TRIGGER link_update BEFORE UPDATE ON Link FOR EACH ROW
  SET NEW.part_zone = (SELECT part_zone FROM Part WHERE part_id = NEW.part_id);