每当我设计数据库时,我总是想知道是否有最好的方法来命名我的数据库中的项目。我经常问自己以下问题:
- 表名应该是复数吗?
- 列名应该是单数吗?
- 我应该为表或列添加前缀吗?
- 我应该在命名项目时使用任何大小写吗?
是否有任何推荐的准则来命名数据库中的项目?
每当我设计数据库时,我总是想知道是否有最好的方法来命名我的数据库中的项目。我经常问自己以下问题:
是否有任何推荐的准则来命名数据库中的项目?
我建议查看 Microsoft 的 SQL Server 示例数据库: https ://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks
AdventureWorks 示例使用非常清晰且一致的命名约定,该约定使用架构名称来组织数据库对象。
这里迟到的答案,但简而言之:
阐述:
(1)你必须做什么。 很少有事情你必须每次都以某种方式做,但也有一些。
(2)你可能应该做什么。
(3)你应该考虑什么。
好的,因为我们正在权衡意见:
我相信表名应该是复数。表是实体的集合(表)。每行代表一个实体,表格代表集合。所以我会称一个 Person 实体表 People(或 Persons,无论你喜欢什么)。
对于那些喜欢在查询中看到单数“实体名称”的人,这就是我使用表别名的目的:
SELECT person.Name
FROM People person
有点像 LINQ 的“从人中选择人名”。
至于 2、3 和 4,我同意@Lars。
我在一个拥有三个 DBA 的数据库支持团队中工作,我们考虑过的选项是:
我们对表使用单数名称。表格往往以系统名称(或其首字母缩写词)作为前缀。如果系统复杂,这很有用,因为您可以更改前缀以将表按逻辑分组(即 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
在开发新项目时,我建议您写出所有首选的实体名称、前缀和首字母缩略词,并将此文档提供给您的开发人员。然后,当他们决定创建一个新表时,他们可以参考文档而不是“猜测”应该调用什么表和字段。
行。那是我的 0.02 美元
我也赞成 ISO/IEC 11179 风格的命名约定,并指出它们是指导方针而不是规定性的。
“表是实体的集合,并遵循集合命名准则。理想情况下,使用一个集合名称:例如,Personnel。复数也是正确的:Employees。不正确的名称包括:Employee、tblEmployee 和 EmployeeTable。”
与往常一样,规则也有例外,例如始终只有一行的表可能会更好地使用单数名称,例如配置表。一致性至关重要:检查您的商店是否有惯例,如果有,请遵守;如果你不喜欢它,那么做一个商业案例来改变它,而不是成为独行侠。
我一直听到这样的论点,即一张桌子是否多元化完全取决于个人品味,没有最佳实践。我不相信这是真的,尤其是作为一名程序员而不是 DBA。据我所知,除了“这对我来说很有意义,因为它是对象的集合”之外,没有任何正当理由将表名复数,而通过使用单数表名可以在代码中获得合法收益。例如:
它避免了由复数歧义引起的错误和错误。程序员并不完全以其拼写专业知识而闻名,并且将某些单词复数会令人困惑。例如,复数词是以“es”结尾还是只是“s”?是人还是人?当您与大型团队一起处理项目时,这可能会成为一个问题。例如,团队成员使用不正确的方法来复数他创建的表的实例。当我与此表交互时,它已在我无权访问或修复所需时间太长的代码中全部使用。结果是我每次使用时都必须记住拼错表格。与此非常相似的事情发生在我身上。您可以让团队的每个成员更轻松地始终如一地轻松使用确切的,正确的表名没有错误或必须一直查找表名,更好。单数版本在团队环境中更容易处理。
如果您使用单数版本的表名并在主键前面加上表名,您现在可以轻松地通过主键确定表名,反之亦然,仅通过代码即可。您可以得到一个包含表名的变量,将“Id”连接到末尾,您现在可以通过代码获得表的主键,而无需进行额外的查询。或者,您可以从主键末尾截去“Id”,以通过代码确定表名。如果您使用没有表名的“id”作为主键,那么您无法通过代码从主键中确定表名。此外,大多数将表名复数并在 PK 列前加上表名的人在 PK 中使用单数形式的表名(例如 statuses 和 status_id),
如果您将表名设为单数,则可以让它们与它们所代表的类名匹配。再一次,这可以简化代码并允许您做一些非常简洁的事情,例如通过只有表名来实例化一个类。它还只是使您的代码更加一致,从而导致...
如果您将表名设为单数,则可以使您的命名方案在每个位置都保持一致、有条理且易于维护。您知道,在代码中的每个实例中,无论是列名、类名还是表名,它都是完全相同的名称。这使您可以进行全局搜索以查看使用数据的任何地方。当您将表名复数时,在某些情况下您将使用该表名的单数版本(它变成的类,在主键中)。没有某些情况下您的数据被称为复数而某些情况下被称为单数是有意义的。
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.
我们的偏好:
表名应该是复数吗?
绝不。它是一个集合的论点是有道理的,但你永远不知道表将包含什么(0,1 或许多项目)。复数规则使命名不必要地复杂。1 栋房子,2 栋房子,老鼠对老鼠,人对人,我们甚至没有看过任何其他语言。
Update person set property = 'value'
作用于表中的每个人。
Select * from person where person.name = 'Greg'
返回人员行的集合/行集。
列名应该是单数吗?
通常,是的,除非您违反规范化规则。
我应该为表或列添加前缀吗?
主要是平台偏好。我们更喜欢在列前加上表名。我们不为表添加前缀,但我们为视图 (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
...长边有点(!)。
我应该在命名项目时使用任何大小写吗?是的 - 小写:),带下划线。这些是非常易读和跨平台的。加上上面的3,它也很有意义。
不过,其中大部分都是偏好。- 只要您保持一致,任何必须阅读它的人都应该可以预测。
看看 ISO 11179-5:命名和识别原则你可以在这里得到它:http: //metadata-standards.org/11179/#11179-5
我在这里写了一段时间的博客:ISO-11179 Naming Conventions
我知道这已经很晚了,并且这个问题已经得到了很好的回答,但是我想就#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%';
我对这些的看法是:
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
我认为没有一套绝对的指导方针。
只要您选择的任何内容在应用程序或数据库中都是一致的,我认为这并不重要。
在我看来:
然而,就像已经提到的那样,任何约定都比没有约定好。无论您选择如何做,都要记录下来,以便将来的修改遵循相同的约定。
我认为您和您的团队将给出每个问题的最佳答案。有一个命名约定比命名约定的精确程度要重要得多。
由于没有正确的答案,您应该花一些时间(但不要太多)并选择自己的约定,并且 -这是重要的部分 - 坚持下去。
当然,最好在这方面寻求一些有关标准的信息,这就是您所要求的,但不要担心或担心您可能得到的不同答案的数量:选择一个看起来更适合您的答案。
以防万一,这是我的答案:
命名约定允许开发团队在项目的核心设计可发现性和可维护性。
一个好的命名约定需要时间来发展,但一旦到位,它就可以让团队使用一种共同的语言向前发展。一个好的命名约定随着项目的发展而有机地发展。一个好的命名约定可以轻松应对软件生命周期中最长和最重要阶段的变化——生产中的服务管理。
以下是我的回答:
命名很困难,但在每个组织中都有可以命名事物的人,并且在每个软件团队中都应该有人负责命名标准,并确保像sec_id、sec_value和security_id这样的命名问题在进入项目之前得到早期解决.
那么好的命名约定和标准的基本原则是什么:-
这是一个提供一些选择的链接。我正在寻找一个我可以遵循的简单规范,而不是不得不依赖一个部分定义的规范。
SELECT
UserID, FirstName, MiddleInitial, LastName
FROM Users
ORDER BY LastName
表名应始终为单数,因为它们代表一组对象。正如你所说的herd 来指定一群羊,或者flock 来指定一群鸟。不需要复数。当表名由两个名称组成并且命名约定是复数时,很难知道复数名称应该是第一个词还是第二个词或两者兼而有之。这是逻辑——Object.instance,而不是objects.instance。或 TableName.column,而不是 TableNames.column(s)。Microsoft SQL 不区分大小写,如果表名由两个或多个名称组成,则如果使用大写字母来分隔表或列名,则更容易阅读表名。
表名:它应该是单数的,因为它是一个单数实体,代表一个真实世界的对象,而不是单数的对象。
列名:它应该是单数的,只有当它表示它将保持一个原子值并确认归一化理论时。但是,如果有 n 个相同类型的属性,则它们应该以 1、2、...、n 等为后缀。
Prefixing Tables / Columns:这是一个很大的话题,稍后会讨论。
外壳:应该是骆驼壳
我的朋友,Patrick Karcher,我请求你不要写任何可能冒犯别人的东西,正如你所写的,“•此外,外键在不同的表中必须一致命名。殴打不这样做的人应该是合法的做这个。”。我的朋友帕特里克我从来没有犯过这个错误,但我写的是一般性的。如果他们一起计划为此打败你怎么办?:)
聚会很晚了,但我仍然想加两分钱关于列前缀
对于列使用 table_column(或 tableColumn)命名标准似乎有两个主要论据,两者都基于列名本身在整个数据库中将是唯一的这一事实:
1) 您不必一直在查询中指定表名和/或列别名
2)您可以轻松地在整个代码中搜索列名
我认为这两个论点都有缺陷。在不使用前缀的情况下解决这两个问题很容易。这是我的建议:
始终在 SQL 中使用表名。例如,始终使用 table.column 而不是 column。
它显然解决了 2),因为您现在可以只搜索 table.column 而不是 table_column。
但我能听到你尖叫,它是如何解决的 1)?正是为了避免这种情况。是的,确实如此,但解决方案存在严重缺陷。为什么?好吧,前缀解决方案归结为:
为了避免在有歧义时必须指定 table.column,您将所有列命名为 table_column!
但这意味着您从现在开始每次指定列时都必须写入列名。但是,如果您无论如何都必须这样做,那么始终显式编写 table.column 有什么好处?确切地说,没有任何好处,输入的字符数完全相同。
编辑:是的,我知道用前缀命名列会强制正确使用,而我的方法依赖于程序员
基本数据库命名约定(和样式)(单击此处获取更多详细说明)
表名选择简短、明确的名称,使用不超过一两个词来区分表 便于命名唯一字段名以及查找和链接表给表提供单数名称,从不复数(更新:我仍然同意给出的原因对于这个约定,但大多数人真的很喜欢复数表名,所以我已经软化了我的立场)......请点击上面的链接
表名单数。假设您正在模拟某人与其地址之间的关系。例如,如果您正在阅读数据模型,您会更喜欢“每个人可能住在 0,1 或多个地址”。或“每个人可能住在 0,1 或多个地址。” 我认为更容易使地址多元化,而不是必须将人重新表述为人。加上集体名词通常与单数形式不同。
--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
);
这些是我被教导的约定,但您应该适应开发软管使用的任何内容。