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

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

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

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

668358 次浏览
  1. 否。表应该以它所代表的实体命名。人,而不是人是指记录中代表的任何人。
  2. 同样的事情。FirstName列实际上不应该被称为FirstNames。这完全取决于您想用该列表示什么。
  3. 没有啦
  4. 是的。为了清晰起见,请使用大小写。如果您需要像“FirstName”这样的列,大小写将使其更易于阅读。

这是我的0.02美元

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

我认为表名应该是复数。表是实体的集合(表)。每行代表一个实体,表代表集合。所以我将Person实体的表称为People(或人,随你喜欢)。

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

SELECT person.NameFROM People person

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

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

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

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

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

为了以防万一,以下是我的答案:

  1. 是的。表是一组记录教师演员,所以……复数。
  2. 是滴
  3. 我不使用它们。
  4. 我经常使用的数据库Firebird将所有内容都保持大写,所以没关系。无论如何,当我编程时,我会以更易于阅读的方式编写名称,例如发布时间
  1. 绝对保持表名单数,人而不是人
    1. 这里也一样
    2. 不,我见过一些可怕的前缀,甚至声明正在处理的是一个表(tbl_)或一个用户存储过程(usp_)。后面跟着库名…不要这样做!
    3. 是的。我倾向于PascalCase我所有的表名

我对此的意见是:

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

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

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

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

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

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

2)他们应该是单数,因为他们只持有一个财产

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

无论你想要什么,我建议Capital Case

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

只要你选择的东西在应用程序或数据库中是一致的,我认为这并不重要。

--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(SELECTD001.ChristianName,D001.Surname,D002.ClassNameFROMD001_Students D001INNER JOIND002_Classes D002OND001.StudentID = D002.StudentID);

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

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

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

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

我们对表使用单数名称。表往往以系统名称(或其首字母缩略词)为前缀。如果您可以更改前缀以将表按逻辑组合在一起(即reg_customer、reg_booking和regadmin_limits),这将非常有用。

对于字段,我们希望字段名称包括表的前缀/丙烯酸(即cust_address1),我们也更喜欢使用标准后缀集(_id为PK,_cd为“代码”,_nm为“名称”,_nb为“数字”,_dt为“日期”)。

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

SELECT cust_nm, cust_add1, booking_dtFROM reg_customerINNER JOIN reg_bookingON reg_customer.cust_id = reg_booking.cust_id

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

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

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

以下是我的回答:

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

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

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

  • 使用客户的语言您的解决方案域
  • 有描述性
  • 保持一致
  • 消歧、反思、重构
  • 不要使用缩写,除非它们大家都很清楚
  • 不要使用SQL保留关键字作为列名

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

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

  1. 表的单数名称
  2. 列的单数名称
  3. 表前缀的架构名称(例如:SchemeName. TableName)
  4. 帕斯卡套管(又名上骆驼套管)

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

我在博客上写了一段时间:ISO-11179命名规范

在我看来:

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

然而,正如前面提到的,任何约定都比没有约定好。无论您选择如何执行,都要将其记录下来,以便将来的修改遵循相同的约定。

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

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

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

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

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

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

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

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

拟订:

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

  • 使用“[sing ularOfTableName]ID”格式命名您的主键。也就是说,无论您的表名是客户还是客户,主键都应该是客户名称
  • 此外,外键必须一致地命名在不同的表中。殴打不这样做的人应该是合法的。我会提出,虽然定义的外键约束是经常重要,但一致的外键命名是总是重要
  • 你的数据库必须有内部惯例。即使在后面的部分你会看到我非常灵活,数据库命名必须非常一致。无论你的客户表是客户还是客户,都不如你在同一个数据库中以同样的方式做重要。你可以抛硬币来决定如何使用下划线,但你必须以同样的方式使用它们。如果你不这样做,你是一个应该自卑的坏人。

(2)你应该做的事

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

(3)你应该考虑的。/强>

  • 我真的认为你应该为表命名复数;有些人认为单数。阅读其他地方的论点。然而,列名应该是单数。即使你使用复数表名,代表其他表组合的表也可能是单数。例如,如果你有一个晋升和一个项目的表,代表促销项目的表可能是Promotions_Items的,但它也可以是合法的Promotion_Items我认为(反映一对多关系)。
  • 一致地为特定目的使用下划线。只是通用表的名称应该在PascalCing中足够清晰;你不需要下划线来分隔单词。保存下划线(a)以指示关联表或(b)作为前缀,我将在下一个项目符号中解决。
  • 前缀既不好也不坏。它通常不是最好的。在你的前一两个数据库中,我不建议使用前缀对表进行一般的主题分组。表最终不容易适合你的类别,实际上它可以使查找表成为第一名。凭借经验,你可以计划和应用一个利大于弊的前缀方案。我曾经在一个数据库中工作过,那里的数据表以tbl开头,配置表以ctbl开头,视图以vew开头,proc的sp,udf的fn,以及其他一些;它被一丝不苟地应用,所以效果很好。唯一需要前缀的情况是,由于某种原因,有不同的解决方案存在于同一个数据库中;前缀对于对表进行分组非常有帮助。前缀也适用于特殊情况,例如您希望突出显示的临时表。
  • 很少(如果有的话)你会想要为列添加前缀。
SELECTUserID, FirstName, MiddleInitial, LastNameFROM UsersORDER BY LastName

我们的偏好:

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

    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之间存在M-M关系(只有某些类型可用于某些类别)

    customer_category_customer_type_id

    …有点(!)在长边。

  4. 我应该在命名项目时使用任何case吗?是的-小写:),带下划线。这些非常可读且跨平台。与上面的3一起也有意义。

    不过,其中大部分都是偏好。-只要你是一致的,任何人都应该可以预测它。

基本数据库命名约定(和样式)(点击这里查看更详细的描述)

表名选择简短,明确的名称,使用不超过一两个单词轻松区分表格便于命名唯一字段名称以及查找和链接表给表起单数名,不要复数(更新:我仍然同意这个惯例的理由,但是大多数人真的喜欢复数表名,所以我软化了我的立场)…请点击上面的链接

表名单数。假设您正在模拟某人与其地址之间的关系。例如,如果你正在阅读一个数据模型,你会喜欢“每个人都可以住在0,1或多个地址。每个人可能住在0,1或多个地址。我认为它更容易复数地址,而不是必须将人们改写为人。加上集体名词往往与单数版本不同。

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

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

例如,给定表“客户”和“地址”,让我们分别使用“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_stateFROM customerINNER JOIN address ON addr_cust_id = cust_idWHERE cust_name LIKE 'J%';

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

列名:它应该是奇异的,只有当它传达它将持有一个原子值并将证实归一化理论时。但是,如果有n个相同类型的属性,那么它们应该后缀1、2、…、n等。

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

案例:应该是骆驼案例

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

表名应始终为单数,因为它们表示一组对象。正如你所说的,牛群指定一组羊,或羊群指定一组鸟。不需要复数。当表名由两个名称组成并且命名惯例是复数时,很难知道复数名称是否应该是第一个单词或第二个单词或两者兼而有之。这是逻辑-Object.instance,不是objects.instance.或TableName.column,不是TableNames.column。MicrosoftSQL不区分大小写,如果使用大写字母,则更容易读取表名,当它们由两个或多个名称组成时,将表名或列名分开。

派对很晚了,但我仍然想添加我的两分钱关于列前缀

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

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

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

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

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

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

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

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

我一直听到这样的争论:表是否被复数完全是个人品味的问题,没有最佳实践。我不相信这是真的,尤其是作为一个与DBA相反的程序员。据我所知,除了“这对我来说很有意义,因为它是对象的集合”之外,没有任何合法的理由对表名进行复数,而使用单数表名在代码中也有合法的收益。例如:

  1. 它避免了由于复数多义性而导致的bug和错误。程序员并不是很擅长拼写,而且一些单词的复数化会让人感到困惑。例如,复数词的结尾是es还是s?它是人还是人?当你在一个有大团队的项目中工作时,这就成了一个问题。例如,一个团队成员使用不正确的方法对他创建的表进行复数化。当我与这个表交互时,它在我无法访问的代码中到处使用,或者需要太长时间才能修复。结果是我每次使用它都必须记住拼错表格。类似的事情也发生在我身上。你越容易让团队中的每个成员都一致地、轻松地使用准确、正确的表名,而不会出错,或者不得不一直搜寻列表名,那就越好。单数版本在团队环境中更容易处理。

  2. 如果你使用单数形式的表名,并在主键前加上表名,你现在可以通过代码轻松地从主键中确定表名,反之亦然。你可以得到一个包含表名的变量,将“Id”连接到末尾,你现在可以通过代码获得表的主键,而无需进行额外的查询。或者你可以从主键的末尾切断“Id”,通过代码确定表名。如果在主键中使用不带表名的id,那么就无法通过代码从主键中确定表名。此外,大多数将表名复数化并在PK列前加上表名的人在PK中使用表名的单数形式(例如状态和status_id),从而根本无法做到这一点。

  3. 如果你让表名单数,你可以让它们匹配它们代表的类名。同样,这可以简化代码并允许你做非常整洁的事情,比如通过只有表名来实例化类。这也只会让你的代码更加一致,从而导致…

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

总而言之,如果你将表名复数化,你将失去使代码更智能、更易于处理的各种优势。甚至可能在某些情况下,你必须使用查找表/数组来将表名转换为你本可以避免的对象或本地代号。单数表名,尽管一开始可能感觉有点奇怪,但比复数名称提供了显着的优势,我相信这是最佳实践。