SQL表外键是复合主键的一部分

时间:2012-10-01 18:59:06

标签: sql sql-server foreign-keys primary-key

是否可以将表的外键作为另一个表的复合主键的一部分? 例如,如果我有两个表,一个包含有关不同用户的所有活动项目的信息,另一个包含有关项目正在使用的设备的信息:

项目表:

Composite Primary Keys: UserId, ProjectId(两者都不是独一无二的)

设备表:

Composite Primary Keys: UserId, ProjectId, EquipmentId(两者都不是独一无二的)

现在可以将设备表中的ProjectId设置为项目表中的外键吗?当我尝试时,我得到一个错误,说项目表中的列与现有的主键或唯一约束不匹配?

3 个答案:

答案 0 :(得分:9)

没有

创建外键时,另一个表中“指向”的键必须是UNIQUE或PRIMARY KEY约束。您无法建立指向允许重复值的列的外键。如果你更新另一个表中的一个重复值(例如),那么很难想象数据应该如何“行动”。(/ p>

要执行您想要的操作,您必须建立一个Projects表,其中ProjectID是UNIQUE或PRIMARY KEY,然后将中的外键其他表中的外键指向该表。

顺便说一句,您使用术语“主键”来描述构成主键的每个表中的列。实际上,每个表可以只有一个主键。该密钥可以由一个或多个列组成,但密钥本身仍然被称为单数。使用主键优化搜索时,这是一个重要的区别。

答案 1 :(得分:0)

它不知道这是否是一个好的设计实践,但可以肯定的是,有一个表的复合外键是其他表的复合主键的一部分。

假设我们有一个表test1,它有一个复合主键(A,B)

现在我们可以有一个表说test2有主键(P,Q,R),其中test2的(P,Q)引用test2(A,B)。

我在MySql数据库中运行了以下脚本,它运行正常。

CREATE TABLE `test1` (
`A` INT NOT NULL,
`B` VARCHAR(2) NOT NULL,
`C` DATETIME NULL,
`D` VARCHAR(45) NULL,
PRIMARY KEY (`A`, `B`));


CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NOT NULL,
`R` INT NOT NULL,
`S` DATETIME NULL,
`T` VARCHAR(8) NULL,
PRIMARY KEY (`P`, `Q`, `R`),
INDEX `PQ_idx` (`P`,`Q` ASC),
CONSTRAINT `PQ`
  FOREIGN KEY (`P`, `Q`)
  REFERENCES `test1` (`A`,`B`)
  ON DELETE CASCADE
  ON UPDATE CASCADE);

在上面提到的情况下,数据库期望(A,B)的组合是唯一的,并且它是test1表中的主键。


但是如果你尝试做类似跟随的事情,脚本就会失败。数据库不允许您创建test2表。

CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NULL,
`R` DATETIME NULL,
`S` VARCHAR(8) NULL,
`T` VARCHAR(45) NULL,
  INDEX `P_idx` (`P` ASC),
  INDEX `Q_idx` (`Q` ASC),
  CONSTRAINT `P`
    FOREIGN KEY (`P`)
    REFERENCES `test1` (`A`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `Q`
    FOREIGN KEY (`Q`)
    REFERENCES `test1` (`B`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);

在上面提到的案例中,数据库会期望列A是唯一的,对于列B也是如此。如果(A,B)的组合是唯一的,则无关紧要。

答案 2 :(得分:-3)

@Larry Lustig 外键可以是另一个表中主键的一部分。

来源:Dependent relationship

检查表之间的关系:Zdarzenie(事件)和TypZdarzenia(事件类型)

football Competition - database