表A和B的外键,其中A已经拥有B

时间:2016-12-10 15:42:13

标签: sql-server database foreign-keys

假设有一个名为帐户的表格:

CREATE TABLE Accounts
(
    [Id] int not null primary key identity(1,1)
    [Username] varchar(20) not null unique,
    [Password] varchar(20) not null
)

然后,还有另一个名为 Characters 的表格。 每个帐户可以包含N个字符。所以我可以使用外键来链接这些字符。

CREATE TABLE Characters
(
    [AccountId] int not null foreign key references Accounts([Id]),
    [Id] int not null primary key identity(1,1),
    [Nickname] varchar(20) not null unique,
    [Level] int not null default 0,
)

每个角色可以有多个设备 (库存),因此有一个设备表。 由于每个设备都链接到一个字符,我应该再次使用外键,这就出现了问题。

我和我的同事正在争论使用哪个外键。 由于每个角色都有一个唯一的ID,我告诉他我们可以使用外键来识别该ID,这就足够了。如下:

CREATE TABLE Equipments
(
    [CharId] int not null foreign key references Characters([Id]),
    [ItemId] int not null
)

他告诉我,我们必须使用字符ID和帐户ID 的外键,如下所示:

CREATE TABLE Equipments
(
    [AccountId] int not null foreign key references Accounts([Id]), /*is this necessary?*/
    [CharId] int not null foreign key references Characters([Id]),
    [ItemId] int not null
)

我不是Sql Server的专家,在我看来,帐号id的外键是完全不必要的,但他一直告诉我必须使用它,它会有助于提高性能,因为你使用的外键越多,它会更好。

那么,我应该使用外键来计算帐户ID和字符ID或字符ID是否足够好?

3 个答案:

答案 0 :(得分:1)

只有当您计划直接查询设备的账户时,才应该使用它,这比通过char加入账户要快。否则,不,你不应该使用它。

答案 1 :(得分:1)

你是对的,但是更重要的原因。

如果在Accountid表中包含Equipments,那么您与Accounts表之间存在第二个关系。也许这是允许的,但很可能,您打算将Characters.AccountId作为Equipments中某行的帐户ID。

然后,您可以使用Equipments表的连接来获取相应的帐户ID。

答案 2 :(得分:1)

正如您所说,AccountCharacter之间存在一对多关系(因此,一个字符不能属于多个帐户)。 同样,如您所述,Equipments中的每条记录仅对应Characters中的唯一记录。因此,可以推断出从AccountEquipments的关系,因此,无需在Equipments表中创建额外的列。此外,数据完整性仅由已创建的两个外键保留,因此当您没有AccountId表中的Equipments列时,这不应该是一个问题。

关于性能参数,这是一个个案的情况,它取决于很多其他事情(记录数,业务逻辑,......)。由于数据库/服务器在运行时需要维护该外键,因此具有不必要的外键甚至可能损害性能。此外,我发现如果您没有密钥,并且当您发现需要密钥时,添加一个密钥比删除现有密钥更容易,尤其是当您必须为此密钥创建一个全新的列时(最后一篇文章仅仅是个人意见。)