数据库,表和列命名约定?

时间:2008-08-11 10:27:23

标签: database database-design language-agnostic naming-conventions

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

  1. 表格名称应该是复数吗?
  2. 列名应该是单数吗?
  3. 我应该为表格或列添加前缀吗?
  4. 我是否应该在命名项目中使用任何案例?
  5. 是否有任何建议的指南用于命名数据​​库中的项目?

23 个答案:

答案 0 :(得分:272)

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

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

  1. 表格的奇异名称
  2. 列的奇异名称
  3. 表格的模式名称前缀(例如:SchemeName.TableName)
  4. 帕斯卡尔外壳(a.k.a。上骆驼箱)

答案 1 :(得分:249)

这里的答案很晚,但简而言之:

  1. 我的偏好是复数
  2. :*通常*没有前缀是最好的。 :否。
  3. 表和列:PascalCase。
  4. 精化:

    (1) 你必须做什么。 你每次都必须以某种方式行事的事情很少,但那里有几个。

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

    (2) 你应该做什么。

    • 表示不同表上相同类型数据的字段的名称应相同。一个表上没有Zip,另一个表上没有ZipCode。
    • 要分隔表名或列名中的单词,请使用PascalCasing。使用camelCasing本质上不会有问题,但这不是惯例,它看起来很有趣。我马上就会解决下划线问题。 (你可能不像过去那样使用ALLCAPS.OBNOXIOUSTABLE.ANNOYING_COLUMN在20年前在DB2中没问题,但现在还没有。)
    • 不要人为地缩短或缩短单词。名字长而清晰比短而且令人困惑更好。超短名称是更黑暗,更野蛮时代的延续。 Cus_AddRef。到底是什么?保管收件人参考?客户额外退款?自定义地址推荐?

    (3) 您应该考虑的事项。

    • 我真的认为你应该有多个表名;有些人认为是单数。阅读别处的论点。但是列名应该是单数。即使您使用多个表名,表示其他表组合的表也可能是单数。例如,如果您有促销表,则表示作为促销一部分的商品的表可以是Promotions_Items,但它也可以合法地为Promotion_Items I思考(反映一对多的关系)。
    • 始终如一地使用下划线并用于特定目的。使用PascalCasing,通用表名称应该足够清晰;你不需要下划线来分隔单词。保存下划线(a)表示关联表或(b)表示前缀,我将在下一个项目符号中解决。
    • 前缀既不好也不坏。 通常不是最好的。在您的第一个数据库中,我不会建议使用前缀来进行表的一般主题分组。表最终不能轻易地适合您的类别,实际上它可以让更难来查找表。根据经验,您可以计划并应用比损害更有益的前缀方案。我在数据表开始时使用 tbl ,使用 ctbl 配置表,使用 vew 查看视图,proc的 sp ,和udf的 fn 等等;它是一丝不苟,一贯地应用,所以它很好。您需要前缀的唯一时间是您有真正独立的解决方案,由于某种原因,它们位于同一个数据库中;为它们添加前缀对于对表进行分组非常有帮助。对于特殊情况,前缀也是可以的,例如您想要突出的临时表。
    • 你想要的很少(如果有的话) 为列添加前缀。

答案 2 :(得分:94)

好的,因为我们正在考虑意见:

我认为表名应该是复数。表是实体的集合(表)。每行代表一个实体,表代表集合。因此,我会调用一个人物实体人员表(或人,无论你想要什么)。

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

SELECT person.Name
FROM People person

有点像LINQ的“来自人选人。名称”。

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

答案 3 :(得分:67)

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

  1. 任何命名标准都优于无标准。
  2. 没有“一个真实的”标准,我们都有自己的偏好
  3. 如果已经有标准,请使用它。不要制定另一个标准或混淆现有标准。
  4. 我们对表格使用单数名称。表格往往以系统名称(或其首字母缩写词)为前缀。如果系统复杂,这很有用,因为您可以更改前缀以逻辑方式将表组合在一起(即.reg_customer,reg_booking和regadmin_limits)。

    对于字段,我们希望字段名称包含表格的前缀/ acryonm(即cust_address1),我们也更喜欢使用标准的后缀集合(PK为_id,“代码”为_cd,_nm对于“name”,_nb表示“number”,_ dt表示“Date”)。

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

    即。

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

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

答案 4 :(得分:44)

  1. 否。表应以它所代表的实体命名。 人,而不是人是你如何指代其中一个记录所代表的人。
  2. 同样的事情。 FirstName列确实不应该被称为FirstNames。这一切都取决于你想用列表示什么。
  3. NO。
  4. 是。为清楚起见,请说明如果你需要像“FirstName”这样的列,外壳会使它更容易阅读。
  5. 确定。这是我的0.02美元

答案 5 :(得分:33)

我也赞成ISO / IEC 11179风格的命名惯例,并指出它们是指导原则,而不是规定性的。

请参阅Data element name on Wikipedia

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

与往常一样,规则例外情况,例如一个总是只有一行的表可能更好用一个单一的名称,例如配置表。一致性至关重要:检查你的商店是否有约定,如果是,请遵循它;如果你不喜欢它,那就做一个商业案例,让它改变而不是单独的游侠。

答案 6 :(得分:24)

我们的偏好:

  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的人,这实际上是视图中的计算字段(无论如何都不能UPDATE)。

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

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

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

    customer.customer_customer_type_id

    表示customer和customer_type表之间的关系,表示customer_type表(customer_type_id)上的主键,如果在调试查询时看到'customer_customer_type_id',则可以立即知道它的来源(客户表)。 / p>

    或者您在customer_type和customer_category之间存在M-M关系(某些类别只能使用某些类型)

    customer_category_customer_type_id

    ...从长远来看有点(!)。

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

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

答案 7 :(得分:21)

我一直听到这样的论点,即一张桌子是否是多元化的,都是个人品味的问题,没有最佳实践。我不相信这是真的,尤其是作为程序员而不是DBA。据我所知,没有合理的理由来复制表名而不是“它对我来说是有意义的,因为它是一个对象的集合”,而在代码中通过具有单个表名来获得合法的收益。例如:

  1. 避免多重歧义造成的错误和错误。程序员并不完全以他们的拼写专业知识而闻名,而且复杂化一些单词令人困惑。例如,复数词是以'es'结尾还是只是's'?是人还是人?当您处理具有大型团队的项目时,这可能会成为一个问题。例如,团队成员使用不正确的方法复数他创建的表的实例。当我与这个表交互时,它在我无法访问的代码中被全部使用,或者需要很长时间才能修复。结果是我必须记住每次使用它时拼错表。与此非常相似的事情发生在我身上。您可以更轻松地让团队的每个成员始终如一地轻松地使用准确,正确的表名而不会出现错误,或者必须始终查找表名,这样做会更好。单一版本在团队环境中更容易处理。

  2. 如果使用表名的单数形式并使用表名作为主键的前缀,则现在可以通过单独的代码轻松地从主键确定表名,反之亦然。您可以为其指定一个带有表名的变量,将“Id”连接到末尾,现在您可以通过代码获得表的主键,而无需执行其他查询。或者您可以从主键的末尾切断“Id”以通过代码确定表名。如果使用“id”而没有主键的表名,则无法通过代码从主键确定表名。此外,大多数使用表名复用表名和PK列的人使用PK中表名的单数形式(例如status和statusId),这使得根本不可能这样做。

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

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

  5. 总而言之,如果您使表名复数化,那么您将失去各种优势,使您的代码更智能,更易于处理。甚至可能存在必须使用查找表/数组将表名转换为可避免的对象或本地代码名称的情况。奇异的表名虽然起初可能有些奇怪,但与多元名称相比具有明显的优势,我相信这是最佳实践。

答案 8 :(得分:19)

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

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

答案 9 :(得分:14)

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

所有列都应使用对其定义的表唯一的前缀命名。

E.g。给定表“customer”和“address”,让我们分别使用“cust”和“addr”的前缀。 “customer”将包含“cust_id”,“cust_name”等。 “address”会有“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%';

答案 10 :(得分:14)

我对这些的看法是:

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

虽然它似乎对简单选择(select * from Orders)有意义,但它对OO等价物(Orders x = new Orders)的意义不大。

DB中的表实际上是该实体的集合,一旦你使用set-logic就更有意义了:

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

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

我不确定总是使用别名(如Matt建议的那样)清除它。

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

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

4)无论你想要什么,我都建议使用CapitalCase

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

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

答案 11 :(得分:13)

在我看来:

  1. 表名应为复数。
  2. 列名应该是单数。
  3. 没有
  4. 表名和列名的CamelCase(我的首选)或underscore_separated。
  5. 然而,正如已经提到的那样,任何惯例都比没有惯例更好。无论您如何选择这样做,请记录下来,以便将来的修改遵循相同的约定。

答案 12 :(得分:11)

  1. 绝对保持表名单数,人不是人
    1. 同样在这里
    2. 否。我已经看到了一些可怕的前缀,甚至可以说明正在处理的是表(tbl_)还是用户存储过程(usp_)。这之后是数据库名称......不要这样做!
    3. 是。我倾向于PascalCase所有的表名

答案 13 :(得分:10)

我认为这些问题的最佳答案将由您和您的团队提供。有一个命名约定,然后命名约定究竟是多么重要。

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

当然,寻找一些关于标准的信息是很好的,这就是你所要求的,但不要担心或担心你可能得到的不同答案的数量:选择一个对你来说更好的答案

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

  1. 是。表格是一组记录教师演员,所以......复数。
  2. 我不使用它们。
  3. 我经常使用的数据库 - Firebird - 将所有内容保持为大写,因此无所谓。无论如何,当我编程时,我会以更易于阅读的方式编写名称,例如 releaseYear

答案 14 :(得分:9)

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

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

以下是我的答案:

  1. 是的,表名称在引用一组交易证券交易对手时应该是复数。
  2. 是。 SQL表以tb_为前缀,视图以vw_为前缀,存储过程以usp_为前缀,触发器以tg_为前缀,后跟数据库名称。
  3. 列名称应为小写字母,以下划线分隔。
  4. 命名很难,但在每个组织中都有人可以命名,在每个软件团队中都应该有人负责仲裁标准并确保命名问题,例如 sec_id sec_value security_id 在它们融入项目之前就会得到解决。

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

    • 使用客户的语言和 您的解决方案域
    • 具有描述性
    • 保持一致
    • 消除歧义,反思和重构
    • 除非他们使用缩写 很清楚每个人
    • 不要使用SQL保留关键字 列名称

答案 15 :(得分:9)

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

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

答案 16 :(得分:5)

SELECT 
   UserID, FirstName, MiddleInitial, LastName
FROM Users
ORDER BY LastName

答案 17 :(得分:5)

表名应始终为单数,因为它们代表一组对象。正如你所说,指定一群绵羊,或群羊确实指定一群鸟。不需要复数。当表名是两个名称的组合并且命名约定是复数时,很难知道复数名称应该是第一个单词还是第二个单词或两者。 它是逻辑 - Object.instance,而不是objects.instance。或TableName.column,而不是TableNames.column。 Microsoft SQL不区分大小写,如果使用大写字母,则更容易读取表名,以便在表名或列名由两个或多个名称组成时将它们分开。

答案 18 :(得分:4)

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

列名:它应该是单数的,然后它传达它将保持原子值并将确认归一化理论。但是,如果有n个相同类型的属性,那么它们应该以1,2,...,n等为后缀。

前缀表/列:这是一个很大的主题,稍后会讨论。

套管:它应该是Camel case

我的朋友, Patrick Karcher ,我请求你不要写任何可能冒犯某人的内容,正如你写的那样,“•此外,外键必须在不同的表格中一致地命名。应该合法地殴打不这样做的人。“我的朋友帕特里克从未犯过这个错误,但我写的一般。如果他们一起打算为此打败你怎么办? :)

答案 19 :(得分:4)

聚会很晚但我还想加上关于列前缀的两分钱

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

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

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

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

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

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

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

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

答案 20 :(得分:3)

Essential Database Naming Conventions (and Style)(点击此处查看详细说明)

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

答案 21 :(得分:2)

表名称单数。假设您正在模拟某人与其地址之间的关系。 例如,如果您正在阅读数据模型,那么您更喜欢 “每个人可能住在0.1或许多地址。”要么 “每个人都可能住在0,1或许多地址。” 我认为它更容易复数地址,而不是必须将人们改写为人。另外,集体名词常常与单数形式不同。

答案 22 :(得分:-3)


--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上限。