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

Database, Table and Column Naming Conventions?

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

  • 表名应该是复数吗?
  • 列名应该是单数吗?
  • 我应该给表或列加前缀吗?
  • 我应该在命名项目时使用任何情况吗?
  • 对于数据库中的命名项目,是否有建议的指导原则?


    我建议签出Microsoft的SQL Server示例数据库:https://github.com/microsoft/sql-server-samples/releases/tag/AdventureWorks

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

  • 表的单数名称
  • 列的单数名称
  • 表前缀的架构名称(例如:schemename.tablename)
  • Pascal外壳(A.K.A.上驼色外壳)

  • 这里回答得晚,但简而言之:

  • 我喜欢复数
  • 是的
  • 表:*通常*没有前缀是最好的。专栏:没有。
  • 表和列:pascalcase。
  • 详述:

    (1)你必须做的。你每次都必须做的事情很少,但也有一些。

    • 使用"[singularoftablename]id"格式命名主键。也就是说,无论您的表名是客户还是客户,主键都应该是customerid。
    • 此外,必须在不同的表中一致地命名外键。殴打不这样做的人应该是合法的。我认为尽管定义的外键约束通常很重要,但是一致的外键命名总是很重要的。
    • 数据库必须有内部约定。即使在后面的部分中,您会看到我非常灵活,但数据库内的命名必须非常一致。无论您的客户表是称为客户还是客户,都不如您在同一个数据库中以相同的方式进行的那样重要。你可以掷硬币决定如何使用下划线,但是你必须以同样的方式使用它们。如果你不这样做,你就是一个应该有低自尊的坏人。

    (2)你应该怎么做。

    • 表示不同表上相同类型数据的字段应命名相同。一张桌子上没有拉链,另一张桌子上没有拉链。
    • 要分隔表名或列名中的单词,请使用pascalcasing。使用camelscasing并不是本质上的问题,但这不是惯例,而且看起来很有趣。我马上就要强调下划线。(你不能像以前那样使用全部大写字母。令人讨厌。恼人的专栏在20年前的DB2中还可以,但现在不行。)
    • 不要人为地缩短或缩写单词。名字长而清楚总比短而混乱好。超短的名字是来自黑暗、野蛮时代的延续。库斯加德雷夫那到底是什么?保管收件人参考?客户额外退款?自定义地址引用?

    (3)你应该考虑什么。

    • 我真的认为你应该用复数形式来表示表格;有些人认为是单数形式。阅读其他地方的论点。不过,列名应该是单数。即使使用复数表名,表示其他表组合的表也可能是单数。例如,如果您有一个促销和一个项目表,表示一个项目是促销的一部分的表可以是促销项目,但它也可以合法地是促销项目,我认为(反映一对多关系)。
    • 始终使用下划线,并用于特定目的。用pascalcashing只需要普通表的名称就足够清晰;不需要下划线来分隔单词。保存下划线,要么(a)表示关联表,要么(b)用于前缀,我将在下一个项目符号中说明。
    • 预混既不好也不坏。这通常不是最好的。在您的前一两个数据库中,我不建议使用前缀对表进行一般主题分组。表最终不容易适应您的类别,而且它实际上会使查找表变得更加困难。有了经验,你可以计划和应用一个比伤害好得多的预混方案。我曾经在一个数据库中工作过,其中数据表以tbl开始,配置表以ctbl开始,视图以vew开始,proc的sp和udf的fn,以及其他一些;它被仔细地、一致地应用,所以效果良好。您唯一需要前缀的时间是,当您拥有真正独立的解决方案时,由于某种原因,这些解决方案驻留在同一个数据库中;在对表进行分组时,对它们进行前缀预处理非常有帮助。在特殊情况下也可以使用前缀,比如要突出的临时表。
    • 你想要的很少(如果有的话)为列加前缀。


    好吧,既然我们在权衡意见:

    我认为表名应该是复数。表是实体的集合(表)。每一行表示一个实体,表表示集合。所以我称之为人-实体-人(或人,随便你怎么想)。

    对于那些希望在查询中看到单一"实体名称"的人,我将使用表别名:

    1
    2
    SELECT person.Name
    FROM People person

    有点像Linq的"从人中选择人。名字"。

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


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

  • 任何命名标准都比没有标准好。
  • 没有"一个真正的"标准,我们都有自己的偏好
  • 如果标准已经到位,请使用它。不要创建其他标准或混淆现有标准。
  • 我们对表使用单数名称。表往往以系统名称(或其缩写)作为前缀。如果系统很复杂,您可以更改前缀以将表逻辑地分组在一起(例如,注册客户、注册预订和注册限制),则此功能非常有用。

    对于字段,我们希望字段名包括表的前缀/字符(即cust_address1),我们还希望使用标准的后缀集(_i d表示pk,_cd表示"code",_nm表示"name",_nb表示"number",_dt表示"date")。

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

    1
    2
    3
    4
    SELECT cust_nm, cust_add1, booking_dt
    FROM reg_customer
    INNER JOIN reg_booking
    ON reg_customer.cust_id = reg_booking.cust_id

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


  • 不可以。表应以其表示的实体命名。"人,而不是人"是指其中一个记录所代表的人。
  • 同样的道理。列firstname真的不应该称为firstname。这完全取决于您想用列表示什么。
  • 不.
  • 对。为清楚起见,请将其包装起来。如果您需要像"firstname"这样的列,那么大小写将使您更容易阅读。
  • 好啊。那是我0.02美元。


    我也支持ISO/IEC11179风格的命名约定,注意到它们是指导原则,而不是规定性的。

    参见维基百科上的数据元素名称:

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

    和往常一样,规则也有例外,例如总是只有一行的表,使用单一名称(例如配置表)可能更好。一致性是最重要的:检查你的商店是否有一个惯例,如果有,遵循它;如果你不喜欢它,那么做一个商业案例来改变它,而不是作为一个独行侠。


    我们的偏好:

  • 表名应该是复数吗?从未。它作为集合的参数是有意义的,但您永远不知道表将包含什么(0、1或许多项)。复数规则使命名变得不必要的复杂。一个房子,两个房子,老鼠对老鼠,人对人,我们甚至没有看过任何其他语言。

    Update person set property = 'value'对桌上的每个人都有作用。Select * from person where person.name = 'Greg'返回人员行的集合/行集。

  • 列名应该是单数吗?通常,是的,除非你违反了正常化规则。

  • 我应该给表或列加前缀吗?主要是平台偏好。我们更喜欢在列前面加上表名。我们不给表加前缀,但我们为视图加前缀(v_u)和存储的程序(sp_u或f_u函数))。这有助于那些想尝试更新vu person.age的人,vu person.age实际上是视图中的一个计算字段(无论如何都不能更新)。

    这也是避免关键字冲突的一个很好的方法(从休息时传递,但从中传递不会)。

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

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

    customer.customer_customer_type_id

    指示客户与客户类型表之间的关系,指示客户类型表(客户类型)上的主键,如果在调试查询时看到"客户客户类型"ID,则可以立即知道它来自何处(客户表)。

    或者在客户类型和客户类别之间存在M-M关系(只有特定类型可用于特定类别)

    customer_category_customer_type_id

    …有点!!)在长边。

  • 我应该在命名项目时使用任何情况吗?是-小写:),带下划线。这些是非常可读和跨平台的。再加上上面的3个,这也是有意义的。

    不过,其中大多数都是偏好。-只要你始终如一,对任何一个必须阅读它的人来说,它应该是可预测的。

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

    我不确定是否总是使用别名(如马特建议的那样)来清除这一点。

    2)它们应该是单数,因为它们只持有1项财产。

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

    4)不管你要什么,我建议你用大写字母。

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

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


    我知道这已经晚了,这个问题已经得到了很好的回答,但我想就列名称的前缀3发表我的意见。

    所有列的命名前缀都应该是它们在中定义的表所特有的。

    例如,给定表"customer"和"address",让我们分别使用前缀"cust"和"addr"。"客户"将在其中包含"客户ID"、"客户名称"等。地址"将包含"addr_id","addr_cust_id"(fk back to customer),"addr_street"等。

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

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

    您可以搜索整个代码库,并可靠地找到每一行与特定列接触的代码。

    从1中获得的好处是难以置信的巨大。我可以取消对列的预测,并准确知道在可以从模式中安全地删除列之前需要更新哪些文件。我可以更改列的含义,并确切知道需要重构什么代码。或者,我可以简单地判断一个列中的数据是否被用于系统的特定部分。我无法计算这将一个可能巨大的项目变为简单项目的次数,也无法计算我们在开发工作中节省的时间。

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

    1
    2
    3
    4
    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%';


    在我看来:

  • 表名应为复数。
  • 列名应为单数。
  • 不。
  • camelcase(我的首选)或下划线_,分别用于表名和列名。
  • 然而,正如前面提到的,任何约定都比没有约定好。无论您如何选择,都要记录下来,以便将来的修改遵循相同的惯例。


  • 一定要保持表名的唯一性,人而不是人。
  • 彼此彼此
  • 不。我见过一些糟糕的前缀,甚至可以说是用来处理表(tbl_u)或用户存储过程(usp_u)。后面跟着数据库名称…不要这样做!
  • 对。我倾向于把我所有的表名都翻过来

  • 我认为这些问题的最佳答案将由你和你的团队给出。有一个命名约定比命名约定的确切程度更重要。

    因为没有正确的答案,你应该花些时间(但不要太多)选择你自己的惯例——这是很重要的一部分——坚持下去。

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

    以防万一,我的答案是:

  • 对。桌子是一组唱片、老师或演员,所以…复数的
  • 对。
  • 我不用它们。
  • 我经常使用的数据库——Firebird——将所有内容都放在大写字母中,所以没关系。不管怎样,当我在编程时,我用一种更容易阅读的方式来写名字,比如releaseyear。

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

    一个好的命名约定需要时间来发展,但是一旦它到位,它就允许团队使用一种通用语言前进。一个好的命名约定随着项目的有机发展而增长。一个好的命名约定可以很容易地处理软件生命周期最长和最重要的阶段——生产中的服务管理中的变更。

    以下是我的答案:

  • 是的,当表名涉及一组交易、证券或交易对手时,表名应为复数。
  • 对。
  • 对。SQL表的前缀为tb_u,视图的前缀为vw_u,存储过程的前缀为usp_u,触发器的前缀为tg_u,后跟数据库名称。
  • 列名应为小写,并用下划线分隔。
  • 命名很难,但在每个组织中都有人可以命名事物,在每个软件团队中,都应该有人负责Namings标准,并确保在将命名问题(如sec-id、sec-value和security-id)放入项目之前尽早解决。

    那么,好的命名规则和标准的基本原则是什么:

    • 使用客户的语言和您的解决方案域
    • 是描述性的
    • 始终如一
    • 消除歧义、反映和重构
    • 不要使用缩写,除非他们每个人都清楚
    • 不要将SQL保留关键字用作列名


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

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


    1
    2
    3
    4
    SELECT
       UserID, FirstName, MiddleInitial, LastName
    FROM Users
    ORDER BY LastName


    表名应该始终是单数的,因为它们代表一组对象。正如你所说的"群"指一组羊,或"群"指一组鸟。不需要复数。当一个表名由两个名称组成,并且命名约定是复数形式时,就很难知道复数名称应该是第一个词还是第二个词,或者两者都是。它是逻辑——object.instance,而不是object s.instance。或tablename.column,而不是tablename.column。Microsoft SQL不区分大小写,如果使用大写字母,则在表名或列名由两个或多个名称组成时,更容易读取表名来分隔表名或列名。


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

    列名:它应该是单数,然后它表示它将保留一个原子值,并符合标准化理论。但是,如果有n个相同类型的属性,那么它们应该加上1、2、…、n等后缀。

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

    外壳:应该是骆驼壳

    我的朋友Patrick Karcher,我请求你不要写任何可能冒犯某人的东西,就像你写的,"?此外,必须在不同的表中一致地命名外键。殴打不这样做的人应该是合法的。我从来没有犯过这样的错误,我的朋友帕特里克,但我一般都在写作。如果他们一起计划为此打败你呢?:)


    参加聚会很晚,但我还是想加上我的两美分关于列前缀的内容。

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

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

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

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

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

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

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

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


    基本数据库命名约定(和样式)(单击此处可获得更详细的描述)

    表名使用不超过一个或两个词的简短、明确的名称容易区分表格便于对唯一字段名以及查找和链接表进行命名给桌子起单数的名字,而不是复数(更新:我仍然同意这个惯例给出的理由,但是大多数人确实喜欢复数的名字,所以我软化了我的立场)。请按上面的链接操作


    表名单数。假设你在模拟某人和他们的地址之间的关系。例如,如果您正在读取数据模型,您是否希望'每个人可以住在0,1或多个地址。'"每个人可能住在0、1或多个地址。"我认为用复数形式表达地址更容易,而不必把人改成人。加上集体名词常常与单数形式不同。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    --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
    );

    这些是我被教导的惯例,但是你应该适应开发软管所使用的任何东西。

  • 复数的它是实体的集合。
  • 对。属性是实体的奇异属性的表示。
  • 是的,前缀表名允许轻松跟踪所有约束索引和表别名的命名。
  • pascal大小写表示表名和列名,前缀+所有索引和约束的大写。