sql - 数据库表中ID列的命名

我想知道人们对数据库表中ID列命名的看法。

如果我有一个名为Invoices的表,其中包含一个标识列的主键,我会调用该列InvoiceID,这样我就不会与其他表发生冲突,而且它显然是什么。

我工作的当前他们已经调用了所有ID列ID。

所以他们会做以下事情:

Select  
    i.ID 
,   il.ID 
From
    Invoices i
    Left Join InvoiceLines il
        on i.ID = il.InvoiceID

现在,我在这里看到一些问题:
1.您需要为select上的列添加别名
2. ID = InvoiceID不适合我的大脑
3.如果你没有对表进行别名并且引用了InvoiceID,它显然是什么表?

关于这个话题的其他人的想法是什么?

Arry asked 2019-09-11T07:54:35Z
24个解决方案
130 votes

我总是首选ID为TableName + ID为id列,然后是TableName + ID为外键。 这样,所有表都具有id字段的相同名称,并且没有冗余描述。 这对我来说似乎更简单,因为所有表都具有相同的主键字段名称。

至于连接表而不知道哪个Id字段属于哪个表,在我看来应该编写查询来处理这种情况。 在我工作的地方,我们总是优先使用表/表别名在语句中使用的字段。

kemiller2002 answered 2019-09-11T07:56:11Z
45 votes

最近在我的公司里,这是关于这件事的书呆子。 LINQ的出现使得冗余的tablename + ID模式在我眼中显得更加愚蠢。 我认为大多数合理的人会说,如果你手工编写SQL,你必须指定表名来区分FK,那么它不仅可以节省打字,而且可以增加你的SQL使用的清晰度 你可以清楚地看到哪个是PK,哪个是FK。

例如。

来自员工e     LEFT JOIN客户c ON e.ID = c.EmployeeID

不仅告诉我这两个是联系的,而且是PK,哪个是FK。 然而,在旧式中你不得不看或希望它们被命名为好。

Echostorm answered 2019-09-11T07:56:51Z
29 votes

我们使用InvoiceID,而不是ID.它使查询更具可读性 - 当您单独看到ID时,它可能意味着什么,尤其是当您将表别名为i时。

Jason Cohen answered 2019-09-11T07:57:16Z
20 votes

ID是SQL Antipattern。请参阅[http://www.amazon.com/s/ref=nb_sb_ss_i_1_5?url=search-alias%3Dstripbooks&field-keywords=sql+antipatterns&sprefix=sql+a]

如果您有许多ID为ID的表,那么您报告的难度就会大得多。 它模糊了含义并使复杂查询更难以阅读,并要求您使用别名来区分报表本身。

此外,如果有人愚蠢到在可用的数据库中使用自然连接,您将加入错误的记录。

如果您想使用某些dbs允许的USING语法,则不能使用ID。

如果您正在使用ID,那么如果您正在复制连接语法,则很容易就会出现错误连接(不要告诉我没有人这样做过!)并且忘记更改连接条件中的别名。

所以你现在拥有

select t1.field1, t2.field2, t3.field3
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t1.id = t3.table2id

当你的意思

select t1.field1, t2.field2, t3.field3 
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t2.id = t3.table2id

如果你使用tablenameID作为id字段,那么这种意外错误就不太可能发生并且更容易找到。

HLGEM answered 2019-09-11T07:55:39Z
19 votes

我同意Kevin和其他一些人的观点,表格的PK应该只是Id而外键列出了其他表格+ Id。

但是,我想补充一个最近给这个论点更加重视的理由。

在我目前的职位上,我们正在使用POCO生成的实体框架。 使用Id的标准命名约定,PK允许继承具有验证的基础poco类,例如对于共享一组公共列名的表。 使用Tablename + Id作为每个表的PK会破坏为这些表使用基类的能力。

只是一些值得思考的东西。

pawnrob answered 2019-09-11T07:58:04Z
10 votes

这并不重要,您可能会遇到所有命名约定中的simalar问题。

但是保持一致非常重要,因此每次编写查询时都不必查看表定义。

Nir answered 2019-09-11T07:58:37Z
10 votes

我的偏好也是主键的ID和外键的TableNameID。 我还想在大多数表中都有一个列“name”,其中我保存了条目的用户可读标识符(即名称:-))。 这种结构在应用程序本身提供了极大的灵活性,我可以以相同的方式处理大量表格。 这是一个非常强大的东西。 通常,OO软件构建在数据库之上,但是由于db本身不允许,因此无法应用OO工具集。 列id和名称仍然不是很好,但它是一个步骤。

选择
i.ID,il.ID来自       发票我       左加入InvoiceLines il           在i.ID = il.InvoiceID上

为什么我不能这样做?

Select  
    Invoices.ID 
,   InvoiceLines.ID 
From
    Invoices
    Left Join InvoiceLines
        on Invoices.ID = InvoiceLines.InvoiceID

在我看来,这非常简单易读。 将变量命名为i和il通常是一个糟糕的选择。

bjdodo answered 2019-09-11T07:59:30Z
7 votes

我刚开始在一个只使用“ID”的地方工作(在核心表中,在外键中由TableNameID引用),并且已经发现了由它直接引起的两个生产问题。

在一种情况下,查询使用“...其中ID为(SELECT ID FROM OtherTable ...”而不是“...其中ID为(SELECT TransID FROM OtherTable ...”)。

任何人都可以诚实地说,如果使用完整,一致的名称,那么错误的陈述会读到“......其中TransID in(SELECT OtherTableID from OtherTable ......”?)我不认为这样会更容易发现吗?我不认为 所以。

重构代码时会出现另一个问题。 如果你使用临时表,而以前查询从核心表中删除,那么旧代码读取“... dbo.MyFunction(t.ID)...”如果没有改变,但“t”现在指的是 临时表而不是核心表,你甚至没有得到错误 - 只是错误的结果。

如果产生不必要的错误是一个目标(也许有些人没有足够的工作?),那么这种命名约定很棒。 否则,一致的命名是要走的路。

Eric Kassan answered 2019-09-11T08:00:22Z
6 votes

为简单起见,大多数人将表名称列在表ID上。 如果它在另一个表上有一个外键引用,那么它们在连接的情况下明确地称它为InvoiceID(使用你的例子),你总是对表进行别名,所以显式的inv.ID仍然比inv.InvoiceID更简单。

Michael Brown answered 2019-09-11T08:00:47Z
4 votes

从正式数据字典的角度来看,我将数据元素命名为employee_last_name.通常,数据元素名称在数据字典中将是唯一的,理想情况下将始终具有相同的名称,但有时可能需要额外的限定条件 基于背景,例如 名为last_name的数据元素可以在组织结构图中使用两次,因此分别限定为PersonnelUNION

显然,命名约定是主观的,是一种风格问题。 我发现ISO / IEC 11179指南是一个有用的起点。

对于DBMS,我将表视为entites的集合(除了那些只包含一行的表,例如cofig表,常量表等),例如 我的employee_last_name是关键的表格将被命名为last_name.所以我立即对Personnel惯例不起作用。

我已经看到了大数据模型上使用的employee_last_name样式,不得不说我发现它有点令人困惑:我更喜欢标识符的名称在整个过程中是相同的,即根据它恰好出现在哪个表中而不更改名称。需要注意的事项。 上面提到的样式似乎是在商店中使用,它为每个表添加last_name(自动增量)列,同时避开外键中的自然键和复合键。 那些商店往往没有正式的数据字典,也没有数据模型。 同样,这只是一个风格问题,而我个人并不赞同。 所以最终,它不适合我。

所有这一切,我可以看到一个案例,当表的名称提供了这样做的上下文时,有时会从列名中删除限定符。 名为employee_last_name的元素可能在Personnel表中变为last_name。 这里的理由是该域名是“人的姓氏”,并且更有可能是UNION,其他表中的列为last_name,而不是在另一个表中用作外键,但是又一次......我可能会改变主意 ,有时你永远无法分辨。 事情就是这样:数据建模是部分艺术,部分科学。

onedaywhen answered 2019-09-11T08:01:44Z
4 votes

我个人更喜欢(如上所述)PK的Table.ID和FK的TableID。 甚至(请不要拍我)Microsoft Access建议这样做。

但是,我也知道一些事实,一些生成工具支持PK的TableID,因为它们倾向于链接包含“ID”字样的所有列名,包括ID!

甚至查询设计器也会在Microsoft SQL Server上执行此操作(对于您创建的每个查询,最终都会删除列ID上所有表上不必要的新创建的关系)

就像我的内部OCD讨厌它一样,我使用TableID约定滚动。 让我们记住,它被称为数据库,因为它将成为许多许多应用程序的基础。 并且所有技术都应该受益于具有清晰描述模式的良好规范化。

不言而喻,当人们开始使用TableName,TableDescription等时,我会画出我的线条。 在我看来,公约应该做到以下几点:

  • 表名:多元化。防爆。 雇员
  • 表别名:全表名称,单数化。防爆。

    SELECT Employee.*, eMail.Address
    FROM Employees AS Employee LEFT JOIN eMails as eMail on Employee.eMailID = eMail.eMailID -- I would sure like it to just have the eMail.ID here.... but oh well
    

[更新]

此外,由于“关系类型”或角色,此线程中有一些关于重复列的有效帖子。 例如,如果商店有一个EmployeeID,那就告诉我蹲下。 所以我有时会做类似Store.EmployeeID_Manager的事情。 当然它有点大,但在leas人们不会疯狂试图找到表ManagerID,或EmployeeID在那里做什么。 当查询是在哪里我会简化为:     将EmployeeID_Manager选择为Manager ID FROM Store

percebus answered 2019-09-11T08:03:12Z
2 votes

只要你保持一致,我认为你可以使用任何东西作为“ID”。 包括表名是很重要的。 我建议使用像Erwin这样的建模工具来强制执行命名约定和标准,这样在编写查询时,很容易理解表之间可能存在的关系。

我的第一个陈述是什么意思,而不是ID,你可以使用像'recno'这样的东西。 那么这个表将有一个invoice_recno的PK,依此类推。

干杯,本

answered 2019-09-11T08:03:51Z
2 votes

我的投票是针对表ID的InvoiceID。 当它用作外键时我也使用相同的命名约定,并在查询中使用智能别名。

 Select Invoice.InvoiceID, Lines.InvoiceLine, Customer.OrgName
 From Invoices Invoice
 Join InvoiceLines Lines on Lines.InvoiceID = Invoice.InvoiceID
 Join Customers Customer on Customer.CustomerID = Invoice.CustomerID

当然,它比其他一些例子更长。 但微笑。 这是为了后代,有一天,一些可怜的初级程序员将不得不改变你的杰作。 在这个例子中没有歧义,并且随着额外的表被添加到查询中,你会感激冗长。

Rob Allen answered 2019-09-11T08:04:23Z
1 votes

对于数据库中的列名,我将使用“InvoiceID”。

如果我通过LINQ将字段复制到一个未命名的结构中,我可以将其命名为“ID”,如果它是结构中唯一的ID。

如果该列不打算在外键中使用,那么它仅用于唯一标识行以进行编辑编辑或删除,我将其命名为“PK”。

James Curran answered 2019-09-11T08:05:03Z
1 votes

如果您为每个密钥指定一个唯一的名称,例如 “invoices.invoice_id”而不是“invoices.id”,那么您可以毫无后顾之忧地使用“自然连接”和“使用”运算符。 例如。

SELECT * FROM invoices NATURAL JOIN invoice_lines
SELECT * FROM invoices JOIN invoice_lines USING (invoice_id)

代替

SELECT * from invoices JOIN invoice_lines
    ON invoices.id = invoice_lines.invoice_id

SQL足够冗长而不会让它变得更加冗长。

Steven Huwig answered 2019-09-11T08:05:38Z
1 votes

我做的是为了保持自己的一致性(表中有一个列的主键用作ID)是命名表的主键Table_pk。我有一个外键指向该表的主键,我调用 列PrimaryKeyTable_fk.这样我就知道如果我的Customer表中有Customer_pk而Order表中有Customer_fk,我知道Order表指的是Customer表中的一个条目。

对我而言,这对于我认为更容易阅读的连接尤其有用。

SELECT * 
FROM Customer AS c
    INNER JOIN Order AS c ON c.Customer_pk = o.Customer_fk
Ian Andrews answered 2019-09-11T08:06:13Z
1 votes

FWIW,我们的新标准(改变,呃,我的意思是“演变”,每个新项目)是:

  • 小写数据库字段名称
  • 大写表名
  • 使用下划线分隔字段名称中的单词 - 在代码中将这些单词转换为Pascal大小写。
  • pk_name_id, first_name, last_name, is_alive,前缀表示主键
  • pk_name_id, first_name, last_name, is_alive,后缀表示整数自动递增ID
  • pk_name_id, first_name, last_name, is_alive,前缀表示外键(不需要后缀)
  • pk_name_id, first_name, last_name, is_alive,视图后缀
  • pk_name_id, first_name, last_name, is_alive,布尔值的前缀

因此,名为NAMES的表可能包含字段pk_name_id, first_name, last_name, is_alive,fk_company以及名为LIVING_CUSTOMERS_VW的视图,定义如下:

SELECT first_name, last_name
FROM CONTACT.NAMES
WHERE (is_alive = 'True')

正如其他人所说的那样,只要它是一致的并且没有不必要地混淆你的意思,任何方案都会起作用。

CMPalmer answered 2019-09-11T08:07:45Z
0 votes

我完全同意在ID字段名称中包含表名,这完全是您给出的原因。 通常,这是我将包含表名的唯一字段。

DOK answered 2019-09-11T08:08:15Z
0 votes

我讨厌普通的id名字。 我强烈希望始终使用invoice_id或其变体。 我总是知道在需要时哪个表是id的权威表,但这让我感到困惑

SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceID = inv.ID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceLineID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceLineID = inv.ID 

最糟糕的是你提到的混合,完全令人困惑。 我不得不使用一个数据库,几乎总是它是foo_id,除了一个最常用的ID。 这完全是地狱。

Vinko Vrsalovic answered 2019-09-11T08:08:52Z
0 votes

我更喜欢DomainName || 'ID'。 (即DomainName + ID)

域名通常(但不总是)与表名相同。

ID本身的问题在于它不会向上扩展。 一旦你有大约200个表,每个表都有一个名为ID的第一列,数据开始看起来都很相似。 如果你总是使用表名来限定ID,这有点帮助,但不是那么多。

DomainName和ID可用于命名外键和主键。 当foriegn键以它们引用的列命名时,可以是助记符助手。 形式上,将外键的名称绑定到它引用的键是没有必要的,因为引用完整性约束将建立引用。 但是在阅读查询和更新方面它非常方便。

偶尔,DomainName || 不能使用“ID”,因为同一个表中有两列具有相同的名称。 示例:Employees.EmployeeID和Employees.SupervisorID。 在这些情况下,我使用RoleName || 'ID',如示例中所示。

最后但并非最不重要的是,我尽可能使用自然键而不是合成键。 在某些情况下,自然键不可用或不可信,但有很多情况下自然键是正确的选择。 在这些情况下,我让自然键采用它自然具有的名称。 这个名字通常甚至没有字母“ID”。 示例:OrderNo其中No是“Number”的缩写。

Walter Mitty answered 2019-09-11T08:09:54Z
0 votes

对于每个表我选择一个树形字母速记(例如Employees => Emp)

这样,数字自动编号主键变为nkEmp。

它很短,在整个数据库中都是独一无二的,我一眼就知道它的属性。

我在SQL和我使用的所有语言中保留了相同的名称(主要是C#,Javascript,VB6)。

pkario answered 2019-09-11T08:10:48Z
0 votes

有关经过深思熟虑的命名表和列系统,请参阅Interakt站点的命名约定。 该方法对每个表使用后缀(对于产品表为idctg_prd,对于类别表为_prd),并将其附加到给定表中的每个列。 因此,products表的标识列为id_prd,因此在数据库中是唯一的。

他们更进一步帮助理解外键:产品表中引用类别表的外键将是idctg_prd,因此很明显它属于哪个表(_prd后缀)以及它引用的表( 类别)。

优点是不同表中的标识列没有歧义,您可以一目了然地通过列名称查询查询所指的列。

flamingLogos answered 2019-09-11T08:11:31Z
0 votes

另请参阅主键/外键命名约定

Mike Henke answered 2019-09-11T08:11:58Z
-2 votes

您可以使用以下命名约定。 它有它的缺点,但它解决了你的特殊问题。

  1. 对表名使用短(3-4个字符)昵称,即Invoice - invl_inv_id,InvoiceLines - invl_id
  2. 使用这些昵称命名表中的列,即invl_inv_id,invl_id
  3. 对于参考列,请使用invl_inv_id作为名称。

这样你就可以说

SELECT * FROM Invoice LEFT JOIN InvoiceLines ON inv_id = invl_inv_id
Ilya Kochetov answered 2019-09-11T08:12:52Z
translate from https://stackoverflow.com:/questions/208580/naming-of-id-columns-in-database-tables