主键/外键命名约定

时间:2009-09-02 19:13:33

标签: sql database-design naming-conventions

在我们的开发组中,我们就主键和外键的命名约定进行了激烈辩论。我们小组基本上有两种思想流派:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

我不想在任何列中复制表的名称(所以我更喜欢上面的选项1)。从概念上讲,它与其他语言中的许多推荐实践一致,在这些实践中,您不在其属性名称中使用对象的名称。我认为命名外键EmployeeID(或Employee_ID可能更好)会告诉读者它是ID表的Employee列。

其他一些人更喜欢选项2,您可以在其中命名前缀为表名的主键,以便整个数据库中的列名相同。我明白了这一点,但你现在无法在视觉上区分主键和外键。

此外,我认为在列名中包含表名是多余的,因为如果您将表视为实体而将列视为该实体的属性或属性,则将其视为ID属性Employee,而不是员工的EmployeeID属性。我不会问我的同事他的PersonAgePersonGender是什么。我问他的年龄是什么。

就像我说的那样,这是一场激烈的争论,我们继续谈论它。我有兴趣获得一些新观点。

13 个答案:

答案 0 :(得分:68)

如果两个表中的两列具有相同的名称(约定#2),则可以在SQL中使用USING语法来保存一些输入和一些样板噪声:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

支持约定#2的另一个论点是the relational model的设计方式。

  

每列的意义​​是   通过标记来部分传达   相应域名。

答案 1 :(得分:45)

这并不重要。我从未遇到过选择1和选择2之间存在真正差异的系统。

杰夫阿特伍德在这个话题上有一篇很棒的文章。基本上人们争论并最激烈地争论那些他们无法证明错误的主题。或者从不同的角度来看,这些话题只能通过基于最后一个人论点的阻挠式耐力来赢得。

选择一个并告诉他们关注实际影响代码的问题。

编辑:如果你想玩得开心,请让他们详细说明为什么他们的方法优于递归表引用。

答案 2 :(得分:12)

我认为这取决于您的应用程序如何组合在一起。如果您使用ORM或设计表来表示对象,那么选项1可能适合您。

我喜欢将数据库编码为自己的图层。我控制一切,应用程序只调用存储过程。结果集具有完整的列名称是很好的,特别是当连接了许多表并返回了许多列时。有了这个应用程序,我喜欢选项2.我真的很想看到列名在连接上匹配。我曾经在他们不匹配的旧系统上工作,这是一场噩梦,

答案 3 :(得分:3)

两种惯例都不适用于所有情况,为什么要有一个?使用常识......

例如,对于自引用表,当有多个FK列自引用同一个表的PK时,您必须违反这两个“标准”,因为两个FK列的名称不能相同。 ..例如,EmployeeTable with EmployeeId PK,SupervisorId FK,MentorId Fk,PartnerId FK,...

答案 4 :(得分:3)

我同意他们之间没什么可选择的。对我来说,关于任一标准的更重要的是“标准”部分。

如果人们开始“做自己的事情”,他们应该被他们的仆人串起来。恕我直言:)

答案 5 :(得分:2)

我工作的惯例非常接近A,除了我们以复数形式命名表(即“employees”)并在表名和列名之间使用下划线。它的好处是,要引用一个列,它可以是“employees _ id”或“employees.id”,具体取决于您希望如何访问它。如果您需要指定列来自哪个表,“employees.employees _ id”肯定是多余的。

答案 6 :(得分:2)

如果您正在查看应用程序代码,而不仅仅是数据库查询,有些事情对我来说似乎很清楚:

  1. 表定义通常直接映射到描述一个对象的类,因此它们应该是单数。为了描述一个对象的集合,我通常将“数组”或“列表”或“集合”附加到单数名称,因为它比使用复数更清楚地表明它不仅是一个集合,而且是一个什么样的集合它是。在该视图中,我看到一个表名不是集合的名称,而是一个集合的对象类型的名称。不编写应用程序代码的DBA可能会忽略这一点。

  2. 我处理的数据通常使用“ID”进行非密钥识别。为了消除关键“ID”和非关键“ID”之间的混淆,对于主键名,我们使用“Key”(即它是什么,不是吗?)前缀为表名或缩写表名。这个前缀(我只为主键保留这个)使得键名称唯一,这一点尤其重要,因为我们使用与数据库列名相同的变量名,并且大多数类都有一个父类,由名称标识父键。这也需要确保它不是保留关键字,单独使用“密钥”。为了便于保持关键变量名一致,并提供进行自然连接的程序,外键与它们作为主键的表中使用的名称相同。我不止一次遇到过使用自然连接以这种方式工作得更好的程序。在最后一点,我承认我使用的自引用表有问题。在这种情况下,我会对外键命名规则进行例外处理。例如,我将使用ManagerKey作为Employee表中的外键,指向该表中的另一条记录。

答案 7 :(得分:2)

我喜欢习俗#2 - 在研究这个主题时,在发布我自己的问题之前找到这个问题,我遇到了以下问题:

我从具有大量列的表中选择*并将其连接到具有大量列的第二个表。两个表都有一个“id”列作为主键,这意味着我必须专门挑选每一列(据我所知),以便在结果中使这两个值唯一,即:

SELECT table1.id AS parent_id, table2.id AS child_id

虽然使用约定#2意味着我仍然会在结果中使用相同名称的某些列,但我现在可以指定我需要的 ID(父或子),正如Steven Huwig建议的那样, USING语句进一步简化了事情。

答案 8 :(得分:2)

我总是在一张桌子上使用 userId 作为PK,而在另一张桌子上使用 userId 作为FK。我正在认真考虑使用 userIdPK userIdFK 作为名称来识别另一个。在查看表时,它将帮助我快速识别PK和FK,并且在使用PHP / SQL访问数据时,它似乎会清除代码,使其更容易理解。特别是当其他人查看我的代码时。

答案 9 :(得分:2)

你考虑过以下几点吗?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee

答案 10 :(得分:1)

我使用约定#2。我正在使用遗留数据模型,我不知道在给定的表中代表什么。啰嗦的伤害在哪里?

答案 11 :(得分:1)

如何命名外键

ROLE_ID

其中role是被引用实体与手头表相关的角色。这解决了递归引用和多个fks到同一个表的问题。

在许多情况下,与引用的表名相同。在这种情况下,它与您的一个提案完全相同。

无论如何,长篇大论是个坏主意

答案 12 :(得分:0)

“在哪里”员工INNER JOIN命令ON order.employee_id = employee.id“是否需要额外的资格?”。

没有必要获得额外的资格,因为我所谈到的资格已经存在。

“业务用户引用订单ID或员工ID的原因是提供上下文,但在dabase级别,您已经拥有上下文,因为您正在引用该表”。

祈祷,告诉我,如果列被命名为“ID”,那么“对表格的引用[原文如何”“是如何完成的,除非通过我所谈到的方式完全符合ID列的这个引用?