为什么表将其主键用作自身的外键


21

浏览数据库时,我遇到了一个表,该表使用其主键作为自身的外键。

我已经看到,表本身可以具有外键来构建层次结构,但是它将使用另一列来引用主键。

由于主键是唯一的,因此在这种情况下行是否只能指向自身?这似乎是一个重言式的链接,因为如果我已经有了该行,那么我已经有了该行。

有什么理由要这样做吗?

表连接到自身

我确定约束是以这种方式编写的(不仅仅是查看图表),因为相同的表和列用于定义的两半。


Answers:


28

就像你说的一样。甲FOREIGN KEY约束引用相同表通常是用于层次结构,它会使用另一列来引用主键。员工表就是一个很好的例子:

EmployeeId    Int     Primary Key
EmployeeName  String
ManagerId     Int     Foreign key going back to the EmployeeId

因此,在这种情况下,有一个从表返回到自身的外键。所有经理也是雇员,因此ManagerId实际上EmployeeId是经理的职责。

现在,另一方面,如果您是说有人使用用作EmployeeId返回Employee表的外键,则可能是一个错误。我确实进行了测试,这是可能的,但并没有任何实际用途。

CREATE TABLE Employee (EmployeeId Int PRIMARY KEY,
                        EmployeeName varchar(50),
                        ManagerId Int);


ALTER TABLE Employee ADD CONSTRAINT fk_employee 
    FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId);

1
如果要“分隔”经理,则在这种情况下对与EmployeeId相关的ManagerId施加约束可能是有益的。如果这样设置,将不允许删除该行。并不是说我会那样做,但是如果您的应用程序依赖具有管理人员的员工,那么它可能会有所帮助。
zgr024 2014年

6

我刚刚在自己的数据库中找到了这样的外键,而且肯定是我自己创建的。我认为这只是偶然发生的。如果我在具有主键的表的上下文菜单中单击“新建外键”(在Management Studio中,SQL 2014 Express),这已经自动创建了一个引用自身的外键。见下文:

在此处输入图片说明

如果那时我没有意识到我应该更改那个而不是添加一个新的,它将保留在那里。或者,如果我只是单击[Close]按钮,这就像[Cancel],则在保存表定义后仍将创建外键。

因此,对我来说,这样的外键是没有意义的,可以删除。


您可能想创建一个FK,并且在此过程中您意识到另一个表尚未设置其PK,因此您取消了,转到另一个表,然后由于某种原因而忘记继续FK流程。那里有递归FK。
安德鲁(Andrew)

4

也许设计师想禁用TRUNCATE TABLE

TRUNCATE TABLE不能在对另一个表具有外键约束的上使用,但是如果有自引用外键可以使用它。从TRUNCATE TABLE(Transact-SQL)的文档中:

BOL提取物

DELETE没有WHERE子句的语句与的作用类似TRUNCATE TABLE(删除表中的所有行),但是该DELETE语句触发删除触发器,这可能是允许的原因,DELETE但不允许这样做TRUNCATE TABLE

我会使用权限来执行此操作(DELETE需要删除权限,TRUNCATE TABLE需要更改表权限),但是也许由于某些原因设计人员无法执行此操作?

注意:尽管设计人员所做的实际上并未禁用TRUNCATE TABLE,但我仍在推测这是他们的意图。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.