在我们的开发组中,我们就主键和外键的命名约定进行了激烈辩论。我们小组基本上有两种思想流派:
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
属性。我不会问我的同事他的PersonAge
或PersonGender
是什么。我问他的年龄是什么。
就像我说的那样,这是一场激烈的争论,我们继续谈论它。我有兴趣获得一些新观点。
答案 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)
如果您正在查看应用程序代码,而不仅仅是数据库查询,有些事情对我来说似乎很清楚:
表定义通常直接映射到描述一个对象的类,因此它们应该是单数。为了描述一个对象的集合,我通常将“数组”或“列表”或“集合”附加到单数名称,因为它比使用复数更清楚地表明它不仅是一个集合,而且是一个什么样的集合它是。在该视图中,我看到一个表名不是集合的名称,而是一个集合的对象类型的名称。不编写应用程序代码的DBA可能会忽略这一点。
我处理的数据通常使用“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列的这个引用?