每当我设计数据库时,我总是想知道是否有最佳方式在数据库中命名项目。我经常问自己以下问题:
- 表名应该是复数吗?
- 列名应为单数吗?
- 我应该为表格或列添加前缀吗?
- 我在命名项目时应该使用大小写吗?
是否有建议的指南来命名数据库中的项目?
每当我设计数据库时,我总是想知道是否有最佳方式在数据库中命名项目。我经常问自己以下问题:
是否有建议的指南来命名数据库中的项目?
Answers:
我建议检查Microsoft的SQL Server示例数据库:https : //github.com/Microsoft/sql-server-samples/releases/tag/adventureworks
AdventureWorks示例使用非常清晰和一致的命名约定,该约定使用模式名称来组织数据库对象。
这里的答案很晚,但总之:
详细说明:
(1)你必须做的。每次 您必须以某种方式执行的事情很少,但也有一些。
(2)您可能应该做什么。
(3)您应该考虑的问题。
CustomerID
该Customer
表是主键还是其他表中的外键。这是一个小问题。你为什么要使用像这样的坏名字c
?CustomerID = Customer.ID
很明显,您会看到您正在将外键与主键连接在一起;这不是多余的,因为双方是两个不同的事物。单字符命名是IMO的不佳做法。
好的,因为我们考虑了很多意见:
我认为表名应为复数。表是实体的集合(表)。每行代表一个实体,表代表集合。因此,我将称一个“人”实体“人”表(或称“人”,无论您喜欢什么)。
对于那些希望在查询中看到单数的“实体名称”的人,这就是我将表别名用于:
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代表“日期”)。
Foriegn键字段的名称应与“主键”字段相同。
即
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样式命名约定,并指出它们是准则而不是说明性的。
“表是实体的集合,并遵循集合命名准则。理想情况下,使用集合名称:例如,人员。复数也是正确的:Employees。不正确的名称包括:Employee,tblEmployee和EmployeeTable。”
像往常一样,规则也有例外,例如始终只有一行的表最好使用单数形式的名称,例如config表。一致性至关重要:检查您的商店是否有约定,如果有,请遵守;如果您不喜欢它,那么请做一个商业案例来对其进行更改,而不要成为唯一的管理员。
我一直都在争辩说,桌子是否复数都是个人喜好,没有最佳实践。我不相信这是真的,尤其是作为程序员而不是DBA。据我所知,除了“对我来说很有意义,因为它是对象的集合”以外,没有其他理由使表名复数,而通过使用单表名可以在代码中获得合法收益。例如:
它避免了由多义性引起的错误和错误。程序员并非以其拼写专业知识而著称,而将某些单词复数会造成混淆。例如,复数词以“ es”结尾还是仅仅是“ s”?是人还是人?当您与大型团队一起进行项目时,这可能会成为问题。例如,团队成员使用不正确的方法对他创建的表进行复数的情况。当我与该表进行交互时,该表已在我无法访问的代码中全部使用,或者需要很长时间才能修复。结果是我必须记住每次使用该表时都会拼写错误。我发生了与此非常相似的事情。您可以更轻松地使团队中的每个成员一致,轻松地使用确切的,正确无误的表名,或者始终需要查找表名的效果更好。单一版本在团队环境中更容易处理。
如果您使用表名的单数形式并在主键之前加上表名,则现在可以轻松地通过代码单独从主键确定表名,反之亦然。可以给您一个带有表名的变量,将“ Id”连接到末尾,现在您可以通过代码获得表的主键,而无需执行其他查询。或者,您可以从主键的结尾处截断“ Id”,以通过代码确定表名。如果使用不带表名的“ id”作为主键,则无法通过代码从主键确定表名。此外,大多数使用表名对表名和PK列加前缀的人都会在PK中使用表名的单数形式(例如statuss和status_id),
如果将表名设为单数,则可以使它们与它们代表的类名匹配。再一次,这可以简化代码,并允许您做一些真正整洁的事情,例如通过仅使用表名来实例化一个类。它还只会使您的代码更加一致,从而导致...
如果将表名设为单数,则将使您的命名方案一致,有条理并且易于在每个位置维护。您知道在代码的每个实例中,无论是在列名,类名还是表名中,它都是相同的名称。这使您可以进行全局搜索以查看使用数据的任何地方。当您对表名进行复数化时,在某些情况下,您将使用该表名的单数形式(它变成主键中的类)。在某些情况下没有数据被称为复数的情况而在某些情况下将单数的情况称为合理。
综上所述,如果您对表名进行复数化处理,则会失去使代码更智能,更易于处理的各种优势。甚至在某些情况下,您必须具有查找表/数组才能将表名转换为可以避免的对象或本地代码名。尽管一开始可能会感到有些奇怪,但单数表名相对于复数名具有明显的优势,我认为这是最佳实践。
我们的偏好:
表名应该是复数吗?
决不。将其作为集合的参数很有意义,但您永远不知道表将包含什么(0,1或许多项目)。多个规则使命名变得不必要地复杂。一栋房子,两栋房子,老鼠与老鼠,人与人,我们甚至都没有看过其他语言。
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和customer_type表之间的关系,表示customer_type表(customer_type_id)上的主键,如果在调试查询时看到“ customer_customer_type_id”,则可以立即知道它来自(customer表)的位置。
或customer_type和customer_category之间有MM关系(仅某些类型可用于某些类别)
customer_category_customer_type_id
...在长边有点(!)。
我在命名项目时应该使用大小写吗?是的-小写:),带下划线。这些都是易读和跨平台的。与上面的3一起也很有意义。
其中大多数是首选项。-只要您保持一致,任何需要阅读的人都应该可以预见。
SELECT * FROM people AS person WHERE person.name = 'Greg'
听起来对我来说是最自然的。
<table name><id>
,例如PersonID
或Person_ID
等。因此,它更有意义,因为每个记录是一个独立的人不是人,你没有名字的复数你的表。
看看ISO 11179-5:命名和识别原理您可以在这里获得:http ://metadata-standards.org/11179/#11179-5
我在这里写过一篇关于它的博客:ISO-11179命名约定
我知道这已经晚了,问题已经得到很好的回答,但是我想就列名的前缀在#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%';
reliably find every line of code that touches a particular column
...不是重点吗?
我对这些的看法是:
1)不,表名应为单数。
尽管对于简单选择(select * from Orders
)似乎很有意义,但对于OO等效项(Orders x = new Orders
)却没有太大意义。
数据库中的表实际上是该实体的集合,一旦使用set-logic,它就更有意义了:
select Orders.*
from Orders inner join Products
on Orders.Key = Products.Key
最后一行,即连接的实际逻辑,看上去与复数的表名混淆了。
我不确定是否总是使用别名(如Matt所建议的那样)可以解决这一问题。
2)它们应为单数,因为它们仅拥有1个财产
3)永远不要,如果列名模棱两可(如上图,它们都具有称为[Key]的列),则表名(或其别名)可以很好地区分它们。您希望查询快速键入且简单-前缀会增加不必要的复杂性。
4)无论您想要什么,我都建议使用CapitalCase
我不认为在这些方面有一套绝对的准则。
只要您选择的内容在整个应用程序或数据库中是一致的,我认为这并不重要。
CapitalCase
什么?
pascal case
Product.ProductName
,Product.ProductID
,Product.ProductPrice
等打字Product.P
给你所有的前缀领域。
我认为您和您的团队将为每个问题提供最佳答案。拥有命名约定远比命名约定的精确度重要得多。
由于没有正确的答案,您应该花一些时间(但不要太多)并选择自己的约定,并且- 这是重要的部分-坚持下去。
当然,这是您所要询问的关于标准的信息,这是很好的,但不要着急或担心您可能会得到的不同答案的数量:选择一个对您来说似乎更好的答案。
以防万一,这是我的答案:
SELECT id,name FROM contacts WHERE email_address LIKE '%gmail%'
表格复数,列单数。再次总是个人意见问题。
命名约定使开发团队可以在项目的核心设计可发现性和可维护性。
好的命名约定需要花费一些时间才能发展,但是一旦到位,就可以使团队继续使用通用语言。良好的命名约定与项目一起自然发展。良好的命名约定可以轻松应对软件生命周期中最长,最重要的阶段(生产中的服务管理)中的更改。
这是我的答案:
命名很困难,但是在每个组织中都有一个可以命名的人,在每个软件团队中都应该有人对命名标准负责,并确保诸如sec_id,sec_value和security_id之类的命名问题在被纳入项目之前尽早得到解决。 。
那么,良好的命名约定和标准的基本原则是什么?
这是一个提供一些选择的链接。我在寻找可以遵循的简单规范,而不必依赖部分定义的规范。
表名应始终为单数,因为它们代表一组对象。正如您说的,牛群代表一群绵羊,羊群代表一群鸟类。无需复数。当表名是两个名字的组成并且命名约定是复数形式时,很难知道复数名称是第一个单词还是第二个单词,或者两者都是。这是逻辑– Object.instance,而不是object.instance。或TableName.column,而不是TableNames.column。Microsoft SQL不区分大小写,如果使用两个大写字母组成的表名或列名,则使用大写字母时,读取表名更容易。
User
是不是一组用户。
表名:它应该是单数形式,因为它是表示现实世界对象的单数实体,而不是表示单数形式的对象。
列名:只有当它表示它将拥有一个原子值并确认归一化理论时,才应为单数。但是,如果有n个相同类型的属性,则应在其后缀1、2,...,n等。
前缀表/列:这是一个巨大的话题,稍后将讨论。
外壳:应该是骆驼壳
我的朋友帕特里克·凯彻(Patrick Karcher),我请您不要写任何可能令人反感的内容,如您所言:“•此外,必须在不同的表中统一命名外键。殴打不这样做的人应该合法。做这个。”。我的朋友帕特里克(Patrick)从未犯过这个错误,但我的写作总体上是这样。如果他们俩计划为此击败您怎么办?:)
晚会很晚,但我仍然想在栏前缀上加上两美分
对于列使用table_column(或tableColumn)命名标准,似乎有两个主要参数,这两个事实都是基于列名本身在整个数据库中是唯一的这一事实:
1)您不必一直在查询中指定表名和/或列别名
2)您可以轻松地在整个代码中搜索列名
我认为这两种说法都是有缺陷的。不使用前缀即可轻松解决这两个问题。这是我的建议:
始终在SQL中使用表名。例如,请始终使用table.column而不是column。
显然,它解决了2),因为您现在可以仅搜索table.column而不是table_column。
但是我能听到你的尖叫声,它如何解决1)?正是要避免这种情况。是的,是的,但是解决方案存在严重缺陷。为什么?好了,前缀解决方案可以归结为:
为了避免在出现歧义时不必指定table.column,请将所有列都命名为table_column!
但这意味着从现在开始,每次指定列时都必须写列名称。但是,如果仍然必须这样做,那么始终显式编写table.column有什么好处?确实,没有好处,因为键入的字符数完全相同。
编辑:是的,我知道用前缀命名列会强制正确使用,而我的方法依赖于程序员
基本数据库命名约定(和样式)(单击此处可获得更详细的描述)
表名选择简短,明确的名称,使用不超过一两个词的区别表就可以轻松地为唯一字段名命名以及查找和链接表赋予表单数名,而不是复数(更新:我仍然同意给出的原因为了这个约定,但是大多数人真的很喜欢复数表名,所以我已经放松了立场。。。请点击上面的链接
e.g. PATIENTS would have a primary key called pa_patient_id_pk
!!
--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
);
这些是我所教的惯例,但是您应该适应您开发软管使用的任何情况。