AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 16616
Accepted
Rachel
Rachel
Asked: 2012-04-18 05:33:15 +0800 CST2012-04-18 05:33:15 +0800 CST 2012-04-18 05:33:15 +0800 CST

为什么人们建议不要将名称“Id”用于标识列?

  • 772

我被教导不要在Id我的表的标识列中使用名称,但最近我一直在使用它,因为它简单、简短,并且非常能描述数据的实际内容。

我见过有人建议在Id表名前加上前缀,但这似乎为编写 SQL 查询的人(或者如果你使用像实体框架这样的 ORM 的程序员)做更多的工作,特别是在较长的表名上,例如CustomerProductId或者AgencyGroupAssignementId

我们聘请的一位第三方供应商为我们创建了一些东西,实际上命名了他们所有的身份列Ident,只是为了避免使用Id. 起初我以为他们这样做是因为Id是关键字,但当我查看它时,我发现这Id不是我们正在使用的 SQL Server 2005 中的关键字。

那么为什么人们建议不要将名称Id用于标识列呢?

编辑:为了澄清,我不是在问要使用哪种命名约定,也不是在询问使用一种命名约定而不是另一种命名约定的参数。我只是想知道为什么不建议使用Id标识列名称。

我是一个程序员,而不是 dba,对我来说,数据库只是一个存储数据的地方。由于我通常构建小型应用程序,并且通常使用 ORM 进行数据访问,因此标识字段的通用字段名称更易于使用。我想知道这样做我错过了什么,以及是否有任何真正好的理由让我不这样做。

naming-convention identity
  • 10 10 个回答
  • 23215 Views

10 个回答

  • Voted
  1. JNK
    2012-04-18T05:41:21+08:002012-04-18T05:41:21+08:00

    表名前缀有很好的理由。

    考虑:

    TableA (id int identity, stringdata varchar(max))
    
    TableB (id int identity, stringdata varchar(max))
    

    我们希望DELETE从TableA两个表中都存在的记录中提取。很简单,我们将只做一个INNER JOIN:

    DELETE a
    FROM 
      TableA A
    INNER JOIN 
      TableB B
        ON b.id = B.id
    

    ....我们刚刚消灭了所有TableA. 我们无意中将 B 的 ID 与自身进行了比较——每条记录都匹配,每条记录都被删除。

    如果字段已命名TableAId,TableBId这将是不可能的 ( Invalid field name TableAid in TableB)。

    就个人而言,我对id在表中使用名称没有任何问题,但是用表名(或实体名称,如果TableA人们PeopleId也可以正常工作)作为前缀确实是一种更好的做法,以避免意外比较错误的字段并吹有事。

    JOIN这也使得在具有大量s的长查询中字段来自何处变得非常明显。

    • 49
  2. db2
    2012-04-18T10:11:46+08:002012-04-18T10:11:46+08:00

    主要是为了防止外键成为巨大的痛苦。假设您有两个表:Customer 和 CustomerAddress。两者的主键都是名为 id 的列,它是一个标识 (int) 列。

    现在您需要从 CustomerAddress 引用客户 ID。显然,您无法命名列 id,因此您使用 customer_id。

    这导致了几个问题。首先,您必须始终记住何时将列称为“id”,何时将其称为“customer_id”。如果你把它搞砸了,它会导致第二个问题。如果您有一个包含十几个连接的大型查询,并且它没有返回任何数据,请玩 Where's Waldo 并找出这个错字:

    ON c.id = ca.id
    

    哎呀,应该是ON c.id = ca.customer_id。或者更好的是,描述性地命名您的身份列,因此它可以是ON c.customer_id = ca.customer_id. 然后,如果您不小心在某处使用了错误的表别名,customer_id 将不会成为该表中的列,并且您将得到一个很好的编译错误,而不是空结果和随后的代码眯眼。

    当然,在某些情况下这无济于事,例如,如果您需要从一个表到另一个表的多个外键关系,但将所有主键命名为“id”也无济于事。

    • 39
  3. Best Answer
    Rachel
    2012-04-19T09:13:53+08:002012-04-19T09:13:53+08:00

    以下是关于从约定中获得的优势的所有答案的摘要,即不对所有主键使用通用名称:

    • 更少的错误,因为身份字段的名称不同

      您不能错误地编写连接B.Id = B.Id而不是 的查询A.Id = B.Id,因为标识字段的名称永远不会完全相同。

    • 更清晰的列名。

      如果您查看名为 的列CustomerId,您会立即知道该列中有哪些数据。如果列名是类似的通用名称Id,那么您还需要知道表名才能知道该列包含哪些数据。

    • 避免不必要的列别名

      您现在可以从与, 而不是SELECT CustomerId, ProductId连接的查询中写入CustomersProductsSELECT Customer.Id as CustomerId, Products.Id as ProductId

    • 允许JOIN..USING语法

      您可以使用语法连接表Customer JOIN Products USING (CustomerId),而不是Customer JOIN Products ON Customer.Id = Products.Id

    • 关键字更容易在搜索中找到

      如果您在大型解决方案中寻找客户的身份字段,搜索CustomerId远比搜索有用Id

    如果您能想到此命名约定的任何其他优点,请告诉我,我会将其添加到列表中。

    是否选择对标识字段使用唯一或相同的列名取决于您,但无论您选择什么,请保持一致:)

    • 31
  4. Izkata
    2012-04-18T08:55:42+08:002012-04-18T08:55:42+08:00

    要从链接的问题中复制我的答案:

    在某些情况下,在每个表上都粘贴“ID”并不是最好的主意:USING关键字(如果受支持)。我们经常在 MySQL 中使用它。

    例如,如果您有fooTablewith columnfooTableId和barTablewith foreign key fooTableId,那么您的查询可以这样构造:

    SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)
    

    它不仅节省了打字,而且与替代方案相比更具可读性:

    SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
    
    • 12
  5. stilgar
    2012-04-18T12:16:57+08:002012-04-18T12:16:57+08:00

    在规范化数据库模式以限制冗余之后,将表划分为具有已建立关系(一对一、一对多、多对多)的较小表。在此过程中,原始表中的单个字段可以出现在多个规范化表中。

    例如,假设 Author_Nickname 具有唯一约束,博客的数据库在其非规范化形式中可能看起来像这样。

    | Author_Nickname | Author_Email | Post_Title | Post_Body |
    +-----------------+--------------+------------+-----------+
    | dave            | [email protected]   | Blah       | Bla bla   |
    | dave            | [email protected]   | Stuff      | I like    |
    | sophie          | [email protected]     | Lorem      | Ipsum     |
    

    规范化它会产生两个表:

    作者:

    | Author_Nickname | Author_Email |
    +-----------------+--------------+
    | dave            | [email protected]   |
    | sophie          | [email protected]     |
    

    邮政

    | Author_Nickname | Post_Title | Post_Body |
    +-----------------+------------+-----------+
    | dave            | Blah       | Bla bla   |
    | dave            | Stuff      | I like    |
    | sophie          | Lorem      | Ipsum     |
    

    这里 Author_Nickname 将是 author 表的主键和 post 表中的外键。即使 Author_Nickname 出现在两个表中,它仍然对应一个信息单元,即。每个列名对应一个字段。

    在许多情况下,原始字段不能有唯一约束,因此使用数字人工字段作为主键。这不会改变每个列名仍然代表一个字段的事实。在传统的数据库设计中,各个列名对应于单个字段,即使它们不是键。(例如,人们会使用part.partname和client.clientname而不是part.name和client.name)。这就是存在 theINNER JOIN ... USING <key>和NATURAL JOIN语法的原因。

    然而,如今,随着 ORM 层在许多语言中很容易获得,数据库通常被设计为面向 OO 语言的持久层,其中在不同类中具有相同作用的变量被称为相同(part.name和client.name,而不是part.partname和client.clientname)。在这种情况下,我倾向于使用“ID”作为主键。

    • 9
  6. Aaron
    2012-04-18T05:59:04+08:002012-04-18T05:59:04+08:00

    我们聘请的一个第三方供应商为我们创建了一些东西,实际上将他们所有的身份列命名为 Ident 只是为了避免使用 Id。

    如果“Ident”最终被用在他们的所有表上,使用“Ident”而不是“Id”并不能真正解决任何问题。

    Drupal 站点上有一篇关于 SQL 编码约定的好文章,指出了这种情况的良好做法:

    最好在表名前加上模块名,以防止可能的命名空间冲突。

    从这个角度来看,CustomerProductId 和 AgencyGroupAssignmentId 使用起来很有意义。是的,它非常冗长。你可以缩短它,但最关心的一点是跟随你的开发者是否会理解你的意思。以详细表名开头的 Id 不应该对它们的含义产生歧义。而且(对我来说)这比节省一些击键更重要。

    • 8
  7. A-K
    2012-04-18T06:23:54+08:002012-04-18T06:23:54+08:00

    我将列命名为 CustomerID 而不是 ID,所以每当我输入

    FROM dbo.Customers AS c JOIN dbo.CustomerOrders AS o
    

    SQL Prompt 立即提出以下建议

    ON c.CustomerID = o.CustomerID 
    

    它为我节省了几次击键。然而,我认为命名约定是非常主观的,因此我对某种方式没有强烈的看法。

    • 7
  8. DForck42
    2012-04-18T07:16:57+08:002012-04-18T07:16:57+08:00

    这与您不会将所有 varchar 字段命名为“UserText”和“UserText1”之类的名称,或者您不会使用“UserDate”和“UserDate1”的原因相同。

    通常,如果您在表中有一个身份字段,则它是您的主键。如果两个表中的主键都是 id,您将如何构建具有父表外键的子表?

    不是每个人都同意这种方法,但在我的数据库中,我为每个表分配了一个唯一的缩写。该表的 PK 将命名为 PK_[abbrv]ID。如果在任何地方用作 FK,那么我将使用 FK_[abbrv]ID。现在我有零猜测工作来弄清楚表关系是什么。

    • 5
  9. jmoreno
    2012-04-18T07:54:50+08:002012-04-18T07:54:50+08:00

    基本上出于同样的原因,您通常不会将参数命名为 parameter1、parameter2 ...它是准确的,但不是描述性的。如果您看到 TableId,那么您可能可以放心地假设它用于保存 Table 的 pk,无论上下文如何。

    至于谁使用了 Ident,他完全没有抓住重点,在 Ident 和 Id 使用 Id 之间进行选择。Ident 比 Id 更令人困惑。

    断章取意,可以假定 Id 是某个表的主键(除非 id 是 guid,否则不是非常有用),但 Ident 甚至没有告诉您(或至少是我)。我最终会发现 Ident 是身份的缩写(一种或另一种方式),但我花在弄清楚这一点上的时间会被浪费掉。

    • 5
  10. DrPizza
    2012-04-18T12:35:35+08:002012-04-18T12:35:35+08:00

    使用前缀,以便可以在主键和外键上下文中使用相同的名称,以便您可以执行natural join/ join ... using。

    • 3

相关问题

  • 我应该使用列命名约定还是依赖列描述?

  • 是否有理由使用极其缩写的表名?

  • 具有共享标识字段的数据库模式

  • 我应该如何最好地命名我的时间戳字段?

  • 命名表和视图时应该遵循什么标准?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve