外键命名方案


152

我只是第一次开始使用外键,我想知道是否有用于它们的标准命名方案?

给定这些表:

task (id, userid, title)
note (id, taskid, userid, note);
user (id, name)

在“任务具有注释”的情况下,“任务”由用户拥有,而“用户”编写注释。

在这种情况下如何命名三个外键?或者,这甚至有关系吗?

更新:此问题是关于外键名称,而不是字段名称!


6
读者注意事项:由于Oracle名称限制为30个字符,因此下面列出的许多最佳实践在Oracle中不起作用。表名或列名可能已经接近30个字符,因此将两者结合成一个单一名称的约定要求使用截断标准或其他技巧。
Charles Burns

Answers:


179

SQL Server中的标准约定为:

FK_ForeignKeyTable_PrimaryKeyTable

因此,例如,注释和任务之间的关键是:

FK_note_task

任务和用户之间的关键是:

FK_task_user

这使您可以“一目了然”查看键中包含哪些表,因此可以轻松查看特定表(第一个命名)依赖于哪些表(第二个命名)。在这种情况下,完整的密钥集将是:

FK_task_user
FK_note_task
FK_note_user

因此,您可以看到任务取决于用户,而注释取决于任务和用户。


1
如果外键指向第二张表上的候选键而不是主键,那么您可能会在名称中使用第三段来限定它。这是一种不寻常的情况,不是您通常从头开始设计的一种情况,因此我没有在响应中包括这一点。
格雷格·比奇

4
您将当前表名包含在键中以使其与众不同。FK名称位于SQL Server的全局命名空间中,因此您不能将两个名为FK_PrimaryKeyTable的FK附加到两个不同的外键表上。对于其他数据库服务器,规则可能有所不同。
格雷格·比奇

好的。在Oracle中,每个表都有不同的名称空间,因此不需要自我引用。
史蒂夫·莫耶

29
这似乎是常见的用法,但是当有两个指向同一张表的外键时,人们该怎么做。即message表有一个from_user_idto_user_id这两个都将成为fk_message_user。在我看来,fk_tablename_columnname出于这个原因,最好使用(在我的示例中为fk_message_from_user_id),然后尝试使您的列名在目标表中保持清晰(即to_user_id显然是在引用用户表)
Code Commander

如果两个表本身都带有下划线,该怎么办?user_role和user_addresses?fk_user_addresses_user_role不会引起混淆吗?
Govi S

38

我使用两个下划线字符作为分隔符,即

fk__ForeignKeyTable__PrimaryKeyTable 

这是因为表名有时会自己包含下划线字符。通常,这遵循约束的命名约定,因为数据元素的名称经常包含下划线字符,例如

CREATE TABLE NaturalPersons (
   ...
   person_death_date DATETIME, 
   person_death_reason VARCHAR(30) 
      CONSTRAINT person_death_reason__not_zero_length
         CHECK (DATALENGTH(person_death_reason) > 0), 
   CONSTRAINT person_death_date__person_death_reason__interaction
      CHECK ((person_death_date IS NULL AND person_death_reason IS NULL)
              OR (person_death_date IS NOT NULL AND person_death_reason IS NOT NULL))
        ...

3
这绝对是最好的答案。
Frederik Krautwald

1
我只是用非常特定的命名约定创建了Derby DB,这里的约定最易读和可追溯。谢谢
Anddo

17

怎么FK_TABLENAME_COLUMNNAME

ķ EEP 牛逼小号 imple 小号 tupid只要有可能。


20
因为当您的数据库很大且包含许多键和表时,并且在软件中进行模式更新时遇到错误,因此即使不搜索数据库创建脚本,也很难找到外键的定义位置。
JohnC 2012年

1
@JohnC如果FK列名在该列名中具有其他表名,那么说起来不容易吗?它告诉您两个表及其定义的列名。例如:“ FK_Animals_OwnerID动物和所有者”表,在OwnerID列上定义
David Sherret,2016年

10

Microsoft关于SQL Server的注释:

一个FOREIGN KEY约束不必仅链接到另一个表中的PRIMARY KEY约束。也可以定义它引用另一个表中UNIQUE约束的列。

因此,我将使用描述依赖项的术语代替常规的主要/外部关系术语。

当通过从属(子)表中类似命名的列引用独立(父)表的PRIMARY KEY时,我忽略了列名:

FK_ChildTable_ParentTable

当引用其他列时,或者两个表之间的列名有所不同,或者只是为了明确起见:

FK_ChildTable_childColumn_ParentTable_parentColumn

9

我通常只留下我的PK命名为id,然后在其他表中命名FK时串联我的表名和键列名。我从不费心地使用骆驼框,因为有些数据库放弃了区分大小写的方式,只是无论如何都返回所有大写或小写名称。无论如何,这是我的表格版本:

task (id, userid, title);
note (id, taskid, userid, note);
user (id, name);

请注意,我还将表命名为单数形式,因为一行代表了我要保留的对象之一。这些约定中有许多是个人喜好。我建议选择一个约定并始终使用它比采用别人的约定更重要。


嘿-这是我实际上使用的确切样式(但使用camelCase)-我认为我会在名称中添加一些额外的说明,以说明它们之间的联系。
尼克

因此,至少我们可以阅读彼此的模式;)...令人尴尬的是,在缺席了两年后无法阅读自己的内容。我们使用ERWin来绘制我们的模式图,但是使用文本版本和使用约定通常可以使您轻松找到表和字段,这通常很方便。
史蒂夫·莫耶

5

这可能是多余的,但对我有用。特别是在处理VLDB时,这对我有很大帮助。我使用以下内容:

CONSTRAINT [FK_ChildTableName_ChildColName_ParentTableName_PrimaryKeyColName]

当然,如果由于某种原因未引用主键,则必须引用唯一约束中包含的列,在这种情况下:

CONSTRAINT [FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName]

能长吗,是的。它是否有助于使信息保持清晰以进行报告,还是让我快速了解了潜在问题是在产品警报期间100%希望了解人们对该命名约定的想法。


1

我通常的做法是

FK_ColumnNameOfForeignKey_TableNameOfReference_ColumnNameOfReference

或者换句话说

FK_ChildColumnName_ParentTableName_ParentColumnName

这样我可以命名引用同一个表像两个外键history_info tablecolumn actionBy and actionTousers_info

就像

FK_actionBy_usersInfo_name - For actionBy
FK_actionTo_usersInfo_name - For actionTo

注意:

我没有包括子表名称,因为对我来说这似乎是常识,因为我在子表中,因此我可以轻松地假定子表的名称。它的总字符为26,非常适合由查尔斯·伯恩斯在此处评论中所述的甲骨文的30个字符限制

读者注意事项:由于其30个字符的名称限制,下面列出的许多最佳实践在Oracle中不起作用。表名或列名可能已经接近30个字符,因此将两者结合成一个单一名称的约定要求使用截断标准或其他技巧。–查尔斯·伯恩斯


如果您的第3个表的FK指向ParentTableName_ParentColumnName相同的表,并且重复FK_Name,则您的表将失败
Tony Dong

0

根据此处的答案和评论,包括FK表,FK字段和PK表(FK_FKTbl_FKCol_PKTbl)的命名约定应避免FK约束名称冲突。

因此,对于此处的给定表:

fk_task_userid_user
fk_note_userid_user

因此,如果您添加一列来跟踪谁最后修改了任务或注释...

fk_task_modifiedby_user
fk_note_modifiedby_user

-2

如果您不是经常使用FK并使用MySQL(和InnoDB),则可以让MySQL为您命名FK。

稍后,您可以通过运行查询找到所需的FK名称


4
我只能解释我的不赞成票。几乎每个数据库系统都允许系统命名约束,您是否可以想象回去并试图在生产问题甚至100张表的数据库中快速找出原因,并试图解释FK__123ee456ff与什么关系?这很简单,只是简单地进行了可怕的练习。当您在此FK上建立索引时,会怎样?系统名称呢?因此,当索引IX_007e373f5963的碎片为98%时,您将如何知道在哪里寻找原因?只是不应该这样做。
SSISPissesMeOff '16

-3

尝试使用大写的版本4 UUID,将第一个八位位组替换为FK和'_'(下划线),而不是'-'(破折号)。

例如

  • FK_4VPO_K4S2_A6M1_RQLEYLT1VQYV
  • FK_1786_45A6_A17C_F158C0FB343E
  • FK_45A5_4CFA_84B0_E18906927B53

基本原理如下

  • 严格的生成算法=> 统一名称 ;
  • 密钥长度小于30个字符,这是Oracle中的命名长度限制(在12c之前);
  • 如果您的实体名称更改,则无需像基于实体名称的方法那样重命名FK(如果DB支持表重命名运算符);
  • 很少使用外键约束的名称。例如,DB工具通常显示约束适用于什么。无需担心神秘的外观,因为您可以避免将其用于“解密”。
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.