引用非主键列的外键约束有哪些缺点?

时间:2011-03-19 23:10:18

标签: sql sql-server database tsql database-design

我想知道使用主键列的参照关系与唯一键列之间是否存在任何缺陷(在SQL Server中,外键约束只能引用主键或唯一索引中的列)。

在特定数据库系统(例如Microsoft SQL Server 2005)中,根据外键是否引用主键与唯一键,在解析查询的方式上是否存在差异?

请注意,我询问使用不同数据类型的列进行参照完整性,连接等之间的区别。

纯粹作为一个例子,假设一个数据库中有一个'查找表'dbo.Offices

CREATE TABLE dbo.Offices (
    ID   int NOT NULL IDENTITY(1,1) CONSTRAINT PK_Codes PRIMARY KEY,
    Code varchar(50) NOT NULL CONSTRAINT UQ_Codes_Code UNIQUE
);

还有一个表dbo.Patients

CREATE TABLE dbo.Patients (
    ID         int NOT NULL IDENTITY(1,1) CONSTRAINT PK_Patients PRIMARY KEY,
    OfficeCode varchar(50) NOT NULL,
    ...
    CONSTRAINT FK_Patients_Offices FOREIGN KEY ( OfficeCode )
        REFERENCES dbo.Offices ( Code )
);

与上面的T-SQL代码相比,表dbo.Patients及其约束FK_Patients_Offices有什么缺点,而不是以下备用版本:

CREATE TABLE dbo.Patients (
    ID       int NOT NULL IDENTITY(1,1) CONSTRAINT PK_Patients PRIMARY KEY,
    OfficeID int NOT NULL,
    ...
    CONSTRAINT FK_Patients_Offices FOREIGN KEY ( OfficeID )
        REFERENCES dbo.Offices ( ID )
);

显然,对于dbo.Patients的第二个版本,如果对{OfficeID列{{}}中的值进行了更改,则不需要更新列Code中的值1}}。

同样(显而易见的)是,使用dbo.Offices Code列进行外键引用很大程度上违背了代理键列dbo.Offices的目的 - 这纯粹是示例的一个工件。 [是否有更好的外键引用可能合理使用非主键的表?]

6 个答案:

答案 0 :(得分:2)

为什么你认为会有任何缺点?

恰恰相反!很高兴看到你按照每个人的意愿执行参照完整性!没有缺点 - 这是一个很好的做法!

我没有看到引用唯一索引与引用主键的任何功能差异或任何问题/问题。


更新:由于您对性能或数据类型相关的问题不感兴趣,因此最后一段可能不会添加任何其他值。

我看到的唯一一件小事是你的OfficeCode都是VARCHAR因此你可能遇到整理和/或套管问题(大/小写,取决于你的整理),相对较大(最多50个字节)和变长字段的JOIN可能不如基于小的固定长度INT列的JOIN条件有效。

答案 1 :(得分:2)

没有缺点。

然而..

为什么在Offices表中有ID列?当在其他表中用作外键时,代理键用于减少空间并提高性能,例如varchar列。

如果要将varchar列用于外键,则不需要代理键。

通过使用FK的Code列,浪费了IDENTITY的大部分好处。

答案 2 :(得分:1)

主键是候选键,与任何其他候选键没有根本区别。广泛遵守的惯例是每个表的一个候选键被指定为“主要”,并且这是用于所有外键引用的键。

以这种方式单独输出一个密钥的一个可能的优点是,您可以将密钥更清楚地用于数据库的用户:他们知道哪个密钥是被引用的密钥而不查看每个引用表。但这完全是可选的。如果你发现方便的话,或者如果要求要求外键引用其他键,那么我建议你这样做。

答案 3 :(得分:0)

我能想到的最重要的一点是,如果他们重新编号办公室,你将失去诚信或需要更新两个表。但可能是这样。

除非您拥有非理性的大型办公室代码,否则性能影响将会非常小,甚至会低于您的预期。

对于大多数人来说,它不被认为是数据库设计的重要决定因素。

答案 4 :(得分:0)

假设你在代码列上添加了一个索引(你应该在引用它时就一定要这么做),是否还有什么可以说不要删除整个ID列并使用代码列作为PK呢?

答案 5 :(得分:-1)

大瑕疵 我们能够在 dbo.Offices.ID 中输入的 dbo.Patients.OfficeID 中输入一些值。 没有任何意义可以说有参考。