855

每当我设计数据库时,我总是想知道是否有最好的方法来命名我的数据库中的项目。我经常问自己以下问题:

  1. 表名应该是复数吗?
  2. 列名应该是单数吗?
  3. 我应该为表或列添加前缀吗?
  4. 我应该在命名项目时使用任何大小写吗?

是否有任何推荐的准则来命名数据库中的项目?

4

23 回答 23

362

我建议查看 Microsoft 的 SQL Server 示例数据库: https ://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks

AdventureWorks 示例使用非常清晰且一致的命名约定,该约定使用架构名称来组织数据库对象。

  1. 表的单数名称
  2. 列的单数名称
  3. 表前缀的模式名称(例如:SchemeName.TableName)
  4. 帕斯卡套管(又名上驼峰壳)
于 2008-08-11T12:39:37.817 回答
335

这里迟到的答案,但简而言之:

  1. 复数表名:我的偏好是复数
  2. 单列名称:
  3. 前缀表或列:
  • 表格:*通常*最好没有前缀。
  • :没有。
  1. 在命名项目时使用任何大小写: PascalCase 用于表和列。

阐述:

(1)你必须做什么。 很少有事情你必须每次都以某种方式做,但也有一些。

  • 使用“[singularOfTableName]ID”格式命名您的主键。也就是说,无论您的表名是Customer还是Customers,主键都应该是CustomerID
  • 此外,外键必须在不同的表中以一致的方式命名。殴打不这样做的人应该是合法的。我会提出,虽然定义的外键约束通常很重要,但一致的外键命名总是很重要
  • 您的数据库必须有内部约定。尽管在后面的部分中您会看到我非常灵活,但数据库中命名必须非常一致。无论您的客户表称为“客户”还是“客户”,都没有您在同一数据库中以相同方式执行此操作重要。你可以掷硬币来决定如何使用下划线,但你必须继续以同样的方式使用它们。如果你不这样做,你就是一个应该自卑的坏人。

(2)你可能应该做什么。

  • 表示不同表上相同类型数据的字段命名相同。不要在一张桌子上使用 Zip,在另一张桌子上使用 ZipCode。
  • 要分隔表名或列名中的单词,请使用 PascalCasing。使用 camelCasing 本质上不会有问题,但这不是惯例,而且看起来很有趣。稍后我将讨论下划线。(您可能不会像过去那样使用 ALLCAPS。OBNOXIOUSTABLE.ANNOYING_COLUMN 在 20 年前的 DB2 中还可以,但现在不行。)
  • 不要人为地缩短或缩写单词。名字长而清晰总比短而混乱好。超短名称是更黑暗、更野蛮时代的遗留物。Cus_AddRef。那到底是什么?保管收件人参考?客户额外退款?自定义地址推荐?

(3)你应该考虑什么。

  • 我真的认为您应该为表格使用复数名称;有些人认为奇异。阅读其他地方的论点。但是,列名应该是单数的。即使您使用复数表名,表示其他表组合的表也可能是单数。例如,如果您有一个Promotions和一个Items表,则表示作为促销一部分的项目的表可能是 Promotions_Items,但我认为它也可能是 Promotion_Items(反映一对多关系)。
  • 始终如一地使用下划线并用于特定目的。使用 PascalCasing 时,一般表名应该足够清晰;您不需要下划线来分隔单词。保存下划线(a)表示关联表或(b)作为前缀,我将在下一个项目符号中解决。
  • 前缀既不好也不坏。这通常不是最好的。在您的第一个或两个数据库中,我不建议对表格的一般主题分组使用前缀。表格最终无法轻松适应您的类别,并且实际上会使查找表格变得更加困难。凭借经验,您可以计划和应用一个利大于弊的前缀方案。我曾经在一个数据库中工作过,其中数据表以tbl开头,以ctbl配置表,以vew、proc 的sp和 udf 的fn开头的视图,以及其他一些人;它一丝不苟,始终如一地应用,所以效果还不错。你唯一需要前缀的时候是当你有真正独立的解决方案时,由于某种原因驻留在同一个数据库中;为它们添加前缀对于对表进行分组非常有帮助。前缀也适用于特殊情况,例如您想要突出的临时表。
  • 您很少(如果有的话)想要为列添加前缀。
于 2010-01-22T16:07:18.463 回答
106

好的,因为我们正在权衡意见:

我相信表名应该是复数。表是实体的集合(表)。每行代表一个实体,表格代表集合。所以我会称一个 Person 实体表 People(或 Persons,无论你喜欢什么)。

对于那些喜欢在查询中看到单数“实体名称”的人,这就是我使用表别名的目的:

SELECT person.Name
FROM People person

有点像 LINQ 的“从人中选择人名”。

至于 2、3 和 4,我同意@Lars。

于 2008-08-11T10:49:03.687 回答
78

我在一个拥有三个 DBA 的数据库支持团队中工作,我们考虑过的选项是:

  1. 任何命名标准都比没有标准好。
  2. 没有“一个真正”的标准,我们都有自己的喜好
  3. 如果已有标准,请使用它。不要创建另一个标准或混淆现有标准。

我们对表使用单数名称。表格往往以系统名称(或其首字母缩写词)作为前缀。如果系统复杂,这很有用,因为您可以更改前缀以将表按逻辑分组(即 reg_customer、reg_booking 和 regadmin_limits)。

对于字段,我们希望字段名称包含表的前缀/acryonm(即 cust_address1),我们也更喜欢使用一组标准的后缀(_id 表示 PK,_cd 表示“代码”,_nm 表示“名称",_nb 表示“数字”,_dt 表示“日期”)。

外键字段的名称应与主键字段的名称相同。

IE

SELECT cust_nm, cust_add1, booking_dt
FROM reg_customer
INNER JOIN reg_booking
ON reg_customer.cust_id = reg_booking.cust_id

在开发新项目时,我建议您写出所有首选的实体名称、前缀和首字母缩略词,并将此文档提供给您的开发人员。然后,当他们决定创建一个新表时,他们可以参考文档而不是“猜测”应该调用什么表和字段。

于 2008-08-11T12:24:17.647 回答
53
  1. 不可以。表应该以其所代表的实体命名。人,而不是人是您如何指代其中一条记录所代表的人。
  2. 再次,同样的事情。FirstName 列确实不应该称为 FirstNames。这完全取决于您想用该列表示什么。
  3. 不。
  4. 是的。为清楚起见。如果您需要像“FirstName”这样的列,则使用大小写会更容易阅读。

行。那是我的 0.02 美元

于 2008-08-11T10:35:10.643 回答
36

我也赞成 ISO/IEC 11179 风格的命名约定,并指出它们是指导方针而不是规定性的。

请参阅Wikipedia 上的数据元素名称

“表是实体的集合,并遵循集合命名准则。理想情况下,使用一个集合名称:例如,Personnel。复数也是正确的:Employees。不正确的名称包括:Employee、tblEmployee 和 EmployeeTable。”

与往常一样,规则也有例外,例如始终只有一行的表可能会更好地使用单数名称,例如配置表。一致性至关重要:检查您的商店是否有惯例,如果有,请遵守;如果你不喜欢它,那么做一个商业案例来改变它,而不是成为独行侠。

于 2008-10-23T10:45:02.153 回答
36

我一直听到这样的论点,即一张桌子是否多元化完全取决于个人品味,没有最佳实践。我不相信这是真的,尤其是作为一名程序员而不是 DBA。据我所知,除了“这对我来说很有意义,因为它是对象的集合”之外,没有任何正当理由将表名复数,而通过使用单数表名可以在代码中获得合法收益。例如:

  1. 它避免了由复数歧义引起的错误和错误。程序员并不完全以其拼写专业知识而闻名,并且将某些单词复数会令人困惑。例如,复数词是以“es”结尾还是只是“s”?是人还是人?当您与大型团队一起处理项目时,这可能会成为一个问题。例如,团队成员使用不正确的方法来复数他创建的表的实例。当我与此表交互时,它已在我无权访问或修复所需时间太长的代码中全部使用。结果是我每次使用时都必须记住拼错表格。与此非常相似的事情发生在我身上。您可以让团队的每个成员更轻松地始终如一地轻松使用确切的,正确的表名没有错误或必须一直查找表名,更好。单数版本在团队环境中更容易处理。

  2. 如果您使用单数版本的表名并在主键前面加上表名,您现在可以轻松地通过主键确定表名,反之亦然,仅通过代码即可。您可以得到一个包含表名的变量,将“Id”连接到末尾,您现在可以通过代码获得表的主键,而无需进行额外的查询。或者,您可以从主键末尾截去“Id”,以通过代码确定表名。如果您使用没有表名的“id”作为主键,那么您无法通过代码从主键中确定表名。此外,大多数将表名复数并在 PK 列前加上表名的人在 PK 中使用单数形式的表名(例如 statuses 和 status_id),

  3. 如果您将表名设为单数,则可以让它们与它们所代表的类名匹配。再一次,这可以简化代码并允许您做一些非常简洁的事情,例如通过只有表名来实例化一个类。它还只是使您的代码更加一致,从而导致...

  4. 如果您将表名设为单数,则可以使您的命名方案在每个位置都保持一致、有条理且易于维护。您知道,在代码中的每个实例中,无论是列名、类名还是表名,它都是完全相同的名称。这使您可以进行全局搜索以查看使用数据的任何地方。当您将表名复数时,在某些情况下您将使用该表名的单数版本(它变成的类,在主键中)。没有某些情况下您的数据被称为复数而某些情况下被称为单数是有意义的。

To sum it up, if you pluralize your table names you are losing all sorts of advantages in making your code smarter and easier to handle. There may even be cases where you have to have lookup tables/arrays to convert your table names to object or local code names you could have avoided. Singular table names, though perhaps feeling a little weird at first, offer significant advantages over pluralized names and I believe are best practice.

于 2013-04-29T19:26:10.883 回答
27

我们的偏好:

  1. 表名应该是复数吗?
    绝不。它是一个集合的论点是有道理的,但你永远不知道表将包含什么(0,1 或许多项目)。复数规则使命名不必要地复杂。1 栋房子,2 栋房子,老鼠对老鼠,人对人,我们甚至没有看过任何其他语言。

    Update person set property = 'value'作用于表中的每个人。
    Select * from person where person.name = 'Greg'返回人员行的集合/行集。

  2. 列名应该是单数吗?
    通常,是的,除非您违反规范化规则。

  3. 我应该为表或列添加前缀吗?
    主要是平台偏好。我们更喜欢在列前加上表名。我们不为表添加前缀,但我们为视图 (v_) 和 stored_procedures(sp_ 或 f_(函数))添加前缀。这有助于想要尝试更新 v_person.age 的人,这实际上是视图中的计算字段(无论如何都无法更新)。

    这也是避免关键字冲突的好方法(delivery.from 中断,但 delivery_from 没有)。

    它确实使代码更加冗长,但通常有助于提高可读性。

    bob = new person()
    bob.person_name = 'Bob'
    bob.person_dob = '1958-12-21'
    ... 非常易读和明确。这可能会失控:

    customer.customer_customer_type_id

    表示客户和 customer_type 表之间的关系,表示 customer_type 表 (customer_type_id) 上的主键,如果您在调试查询时看到“customer_customer_type_id”,您会立即知道它来自哪里(客户表)。

    或者您在 customer_type 和 customer_category 之间有 MM 关系(只有某些类型可用于某些类别)

    customer_category_customer_type_id

    ...长边有点(!)。

  4. 我应该在命名项目时使用任何大小写吗?是的 - 小写:),带下划线。这些是非常易读和跨平台的。加上上面的3,它也很有意义。

    不过,其中大部分都是偏好。- 只要您保持一致,任何必须阅读它的人都应该可以预测。

于 2010-03-26T13:58:16.517 回答
23

看看 ISO 11179-5:命名和识别原则你可以在这里得到它:http: //metadata-standards.org/11179/#11179-5

我在这里写了一段时间的博客:ISO-11179 Naming Conventions

于 2008-08-11T13:13:58.747 回答
17

我知道这已经很晚了,并且这个问题已经得到了很好的回答,但是我想就#3 关于列名的前缀提出我的意见。

所有列都应该使用一个前缀来命名,该前缀对于定义它们的表来说是唯一的。

例如,给定表“customer”和“address”,让我们分别使用前缀“cust”和“addr”。“客户”将包含“cust_id”、“cust_name”等。“地址”将包含“addr_id”、“addr_cust_id”(FK 回客户)、“addr_street”等。

当我第一次看到这个标准时,我坚决反对它。我讨厌这个主意。我无法忍受所有额外的打字和冗余的想法。现在我已经有足够的经验了,我再也不会回去了。

这样做的结果是数据库模式中的所有列都是唯一的。这样做有一个主要好处,它胜过所有反对它的论点(当然,在我看来):

您可以搜索整个代码库并可靠地找到涉及特定列的每一行代码。

#1的好处是非常巨大的。我可以弃用一个列,并确切知道需要更新哪些文件,然后才能安全地从架构中删除该列。我可以更改列的含义并确切知道需要重构哪些代码。或者我可以简单地判断列中的数据是否正在系统的特定部分中使用。我数不清有多少次把一个潜在的巨大项目变成一个简单的项目,也数不清我们在开发工作中节省的时间。

另一个相对较小的好处是,您只需在进行自联接时使用表别名:

SELECT cust_id, cust_name, addr_street, addr_city, addr_state
    FROM customer
        INNER JOIN address ON addr_cust_id = cust_id
    WHERE cust_name LIKE 'J%';
于 2011-09-02T22:19:26.930 回答
16

我对这些的看法是:

1) 不,表名应该是单数。

虽然对于简单的选择 ( select * from Orders) 似乎有意义,但对于 OO 等效项 ( Orders x = new Orders) 来说意义不大。

数据库中的表实际上是该实体的集合,一旦您使用集合逻辑,它就更有意义:

select Orders.*
from Orders inner join Products
    on Orders.Key = Products.Key

最后一行,连接的实际逻辑,看起来与复数表名混淆。

我不确定是否总是使用别名(正如马特建议的那样)可以解决这个问题。

2) 它们应该是单数的,因为它们只拥有 1 个属性

3) 从不,如果列名不明确(如上所示,它们都有一个名为 [Key] 的列),则表的名称(或其别名)可以很好地区分它们。您希望查询输入快速且简单 - 前缀会增加不必要的复杂性。

4) 无论你想要什么,我都会推荐 CapitalCase

我认为没有一套绝对的指导方针。

只要您选择的任何内容在应用程序或数据库中都是一致的,我认为这并不重要。

于 2008-08-11T11:27:56.230 回答
14

在我看来:

  1. 表名应该是复数。
  2. 列名应该是单数。
  3. 不。
  4. CamelCase(我的首选)或 underscore_separated 用于表名和列名。

然而,就像已经提到的那样,任何约定都比没有约定好。无论您选择如何做,都要记录下来,以便将来的修改遵循相同的约定。

于 2008-08-11T15:23:32.027 回答
11

我认为您和您的团队将给出每个问题的最佳答案。有一个命名约定比命名约定的精确程度要重要得多。

由于没有正确的答案,您应该花一些时间(但不要太多)并选择自己的约定,并且 -是重要的部分 - 坚持下去。

当然,最好在这方面寻求一些有关标准的信息,这就是您所要求的,但不要担心或担心您可能得到的不同答案的数量:选择一个看起来更适合您的答案。

以防万一,这是我的答案:

  1. 是的。表是一组记录教师演员,所以...复数。
  2. 是的。
  3. 我不使用它们。
  4. 我经常使用的数据库——Firebird——将所有内容都保持为大写,所以没关系。无论如何,当我编程时,我会以更容易阅读的方式编写名称,例如releaseYear
于 2008-08-11T11:14:11.937 回答
11
  1. 绝对保持表名单数,人而不是人
    1. 同样在这里
    2. 不,我见过一些可怕的前缀,甚至表明正在处理的是表 (tbl_) 或用户存储过程 (usp_)。这后跟数据库名称......不要这样做!
    3. 是的。我倾向于 PascalCase 我所有的表名
于 2008-08-11T11:24:50.823 回答
9

命名约定允许开发团队在项目的核心设计可发现性和可维护性。

一个好的命名约定需要时间来发展,但一旦到位,它就可以让团队使用一种共同的语言向前发展。一个好的命名约定随着项目的发展而有机地发展。一个好的命名约定可以轻松应对软件生命周期中最长和最重要阶段的变化——生产中的服务管理。

以下是我的回答:

  1. 是的,例如,当表名指代一组交易证券交易对手时,表名应该是复数。
  2. 是的。
  3. 是的。SQL 表以 tb_ 为前缀,视图以 vw_ 为前缀,存储过程以 usp_ 为前缀,触发器以 tg_ 为前缀,后跟数据库名称。
  4. 列名应为小写,并用下划线分隔。

命名很困难,但在每个组织中都有可以命名事物的人,并且在每个软件团队中都应该有人负责命名标准,并确保像sec_idsec_valuesecurity_id这样的命名问题在进入项目之前得到早期解决.

那么好的命名约定和标准的基本原则是什么:-

  • 使用您的客户和您的解决方案领域的语言
  • 具有描述性
  • 始终如一
  • 消除歧义、反映和重构
  • 除非每个人都清楚,否则不要使用缩写
  • 不要使用 SQL 保留关键字作为列名
于 2008-08-11T12:27:27.670 回答
9

这是一个提供一些选择的链接。我正在寻找一个我可以遵循的简单规范,而不是不得不依赖一个部分定义的规范。

http://justinsomnia.org/writings/naming_conventions.html

于 2008-10-22T17:05:31.713 回答
9
SELECT 
   UserID, FirstName, MiddleInitial, LastName
FROM Users
ORDER BY LastName
于 2010-01-22T23:19:44.657 回答
5

表名应始终为单数,因为它们代表一组对象。正如你所说的herd 来指定一群羊,或者flock 来指定一群鸟。不需要复数。当表名由两个名称组成并且命名约定是复数时,很难知道复数名称应该是第一个词还是第二个词或两者兼而有之。这是逻辑——Object.instance,而不是objects.instance。或 TableName.column,而不是 TableNames.column(s)。Microsoft SQL 不区分大小写,如果表名由两个或多个名称组成,则如果使用大写字母来分隔表或列名,则更容易阅读表名。

于 2012-06-25T10:18:06.923 回答
4

表名:它应该是单数的,因为它是一个单数实体,代表一个真实世界的对象,而不是单数的对象。

列名:它应该是单数的,只有当它表示它将保持一个原子值并确认归一化理论时。但是,如果有 n 个相同类型的属性,则它们应该以 1、2、...、n 等为后缀。

Prefixing Tables / Columns:这是一个很大的话题,稍后会讨论。

外壳:应该是骆驼壳

我的朋友,Patrick Karcher,我请求你不要写任何可能冒犯别人的东西,正如你所写的,“•此外,外键在不同的表中必须一致命名。殴打不这样做的人应该是合法的做这个。”。我的朋友帕特里克我从来没有犯过这个错误,但我写的是一般性的。如果他们一起计划为此打败你怎么办?:)

于 2011-09-24T13:08:53.873 回答
4

聚会很晚了,但我仍然想加两分钱关于列前缀

对于列使用 table_column(或 tableColumn)命名标准似乎有两个主要论据,两者都基于列名本身在整个数据库中将是唯一的这一事实:

1) 您不必一直在查询中指定表名和/或列别名

2)您可以轻松地在整个代码中搜索列名

我认为这两个论点都有缺陷。在不使用前缀的情况下解决这两个问题很容易。这是我的建议:

始终在 SQL 中使用表名。例如,始终使用 table.column 而不是 column。

它显然解决了 2),因为您现在可以只搜索 table.column 而不是 table_column。

但我能听到你尖叫,它是如何解决的 1)?正是为了避免这种情况。是的,确实如此,但解决方案存在严重缺陷。为什么?好吧,前缀解决方案归结为:
为了避免在有歧义时必须指定 table.column,您将所有列命名为 table_column!
但这意味着您从现在开始每次指定列时都必须写入列名。但是,如果您无论如何都必须这样做,那么始终显式编写 table.column 有什么好处?确切地说,没有任何好处,输入的字符数完全相同。

编辑:是的,我知道用前缀命名列会强制正确使用,而我的方法依赖于程序员

于 2012-12-03T09:11:42.430 回答
3

基本数据库命名约定(和样式)(单击此处获取更多详细说明)

表名选择简短、明确的名称,使用不超过一两个词来区分表 便于命名唯一字段名以及查找和链接表给表提供单数名称,从不复数(更新:我仍然同意给出的原因对于这个约定,但大多数人真的很喜欢复数表名,所以我已经软化了我的立场)......请点击上面的链接

于 2011-05-05T06:08:50.227 回答
2

表名单数。假设您正在模拟某人与其地址之间的关系。例如,如果您正在阅读数据模型,您会更喜欢“每个人可能住在 0,1 或多个地址”。或“每个人可能住在 0,1 或多个地址。” 我认为更容易使地址多元化,而不是必须将人重新表述为人。加上集体名词通常与单数形式不同。

于 2011-06-26T19:18:57.333 回答
-4

--Example SQL

CREATE TABLE D001_Students
(
    StudentID INTEGER CONSTRAINT nnD001_STID NOT NULL,
    ChristianName NVARCHAR(255) CONSTRAINT nnD001_CHNA NOT NULL,
    Surname NVARCHAR(255) CONSTRAINT nnD001_SURN NOT NULL,
    CONSTRAINT pkD001 PRIMARY KEY(StudentID)
);

CREATE INDEX idxD001_STID on D001_Students;

CREATE TABLE D002_Classes
(
    ClassID INTEGER CONSTRAINT nnD002_CLID NOT NULL,
    StudentID INTEGER CONSTRAINT nnD002_STID NOT NULL,
    ClassName NVARCHAR(255) CONSTRAINT nnD002_CLNA NOT NULL,
    CONSTRAINT pkD001 PRIMARY KEY(ClassID, StudentID),
    CONSTRAINT fkD001_STID FOREIGN KEY(StudentID) 
        REFERENCES D001_Students(StudentID)
);

CREATE INDEX idxD002_CLID on D002_Classes;

CREATE VIEW V001_StudentClasses
(
    SELECT
        D001.ChristianName,
        D001.Surname,
        D002.ClassName
    FROM
        D001_Students D001
            INNER JOIN
        D002_Classes D002
            ON
        D001.StudentID = D002.StudentID
);

这些是我被教导的约定,但您应该适应开发软管使用的任何内容。

  1. 复数。它是实体的集合。
  2. 是的。属性是实体的单一属性的表示。
  3. 是的,前缀表名允许轻松跟踪所有约束索引和表别名的命名。
  4. 表名和列名的 Pascal Case,索引和约束的前缀 + ALL 大写。
于 2008-08-11T11:46:05.617 回答