我曾经在数据库中为列添加标签,如下所示:

user_id
user_name
user_password_hash


为了避免在连接两个表时发生冲突,但是后来我学到了更多关于如何别名表的知识,停止这样做。

在数据库中标记列的有效方法是什么?为什么?

评论

哪个数据库?我在Oracle中的标签方式与大多数其他数据库不同,这是由于它具有自动选择列名(如果名称匹配)的基础的功能。

@Joe,好吧,我一直使用MySQL和SQLite3,但是它应该适用于大多数其他数据库。

@joe从未注意到Oracle是与众不同的。你能给个链接吗?

@bernd_k:我在下面的答案中添加了一些链接

#1 楼

在您的情况下,前缀用户是多余的。我们(负责开发的人)知道这是表用户,所以为什么在每个字段前面添加user_前缀?

我建议您使用一种更自然的方法来做到这一点。

一个人的特征是什么:姓氏,名字,生日,国籍等...

汽车的特征是什么:型号,年份,颜色,能量等...

您的列应命名为尽可能自然的名称,这将使每个人,您和您之后的人的架构都更加清晰。这也称为维护阶段,您可以做的任何使维护变得容易的事情通常都是值得的。

评论


是的,当人们这样做时,我很生气。同样,当他们调用所有表tbl_whatever时。

– Gaius
2011年1月10日下午13:31

这也与“类词”的概念有关,当类词是否适用时,社区中似乎存在一些争论。 (类词是一种工具,用于:识别数据的不同类别或分类,描述由数据名称描述的数据类型,以及描述与数据元素相关联的数据的主要分类。)

–乔恩·史宁(Jon Schoning)
2011年4月29日17:50



#2 楼

除了Spredzy的注释之外,您还可以将主键标记为相同的ID(ID),以便在即时编写查询时,您可以轻松地调用(u.ID = c.ID),而不必查找“ Was it countryID” ,country_ID,国家/地区ID,国家/地区ID 、?“

评论


我曾经在一个数据库上工作,DBA决定在某些表中使用ID,而在另一些表中使用ID,并且我们将MySQL设置为区分大小写...好玩!

–托比
2011年1月3日在21:03

我们通常使用tablename.tablename_id。例如。 car.car_id; person.person_id。表的单数名称。

– glasnt
2011年1月3日,21:34

@glasnt明智的决定。

– Garik
2011年1月7日17:39

这实际上是一个非常糟糕的主意,并且您将失去使用SQL USING子句的能力(这违反规范)。

–埃文·卡洛尔(Evan Carroll)
18 Mar 27 '18 at 19:04

#3 楼

我完全同意戴维·霍尔(David Hall)对Spredzy出色回答的补遗。简单自然是您要走的路。如果您也自然地命名表,那么表混乱就不会成为问题。

如果您可以拥有users.id和cars.id,则没有users.user_id和cars.car_id

#4 楼

我认为在数据库模式中,每列在表之间应具有唯一的名称。造成这种情况的原因有很多:从建模的角度来看:从大量的属性开始,然后将其规范化为表格。随着时间的流逝,您可能会进一步规范化或规范化,或者引入视图或实例化视图,或者引入新表。如果所有列名都是唯一的,这将永远不是问题。
您可以使用以下连接语法:a JOIN b USING (a_id) JOIN c USING (a_id)。非常方便,还可以帮助您解决以下问题。
如果运行带有大量联接的查询或使用SELECT *创建物化视图,则您永远不会(或者可能很少)发生冲突。考虑加入person.nameproduct.namecountry.name等。Urgh。
通常,如果您有很大的疑问,则很难跟踪id在任何地方的含义。


评论


例如,您如何命名员工姓名和站点名称列?您将如何避免名称标签列的冗余?

–疯狂
2011年1月3日,22:21

@Spredzy:我只会考虑冗余。

– Peter Eisentraut
2011年1月4日,下午4:52

这些问题的答案是:别名。

–万事通
2011年10月4日在21:12

#5 楼

让我们来看一下您的示例,它看起来像这样:

USERS
----
id
username,
password
registration_date


我使用大写的表名。这使我可以轻松识别表格。我刚刚命名的列各代表其含义。我尽量不要使用数字或不使用任何前缀或后缀。这将使查询变得简单而直接。

顺便说一句,我认为您应该找到自己喜欢的样式并坚持使用。如果您经常更改它,那么您将拥有一个更混乱的数据库架构。

评论


+1表示“找到喜欢的风格并坚持下去”。一致性比完全符合任何特定标准要好(尽管如果您尚未选择标准,则某些标准会比其他标准更好)。

–万事通
2011年10月4日在21:10

#6 楼

像其他人一样,我建议您不要在表中包括表名。除非您有成百上千个具有几乎相同的列名的表:如果您有数十个表都具有一个标题为ID的列,则务必以表名作为前缀。

我最近离开了一家公司,其中一位开发人员更喜欢在主键和外键列前加上pk和fk。这导致某些令人讨厌的情况,其中列以pkfk开头(通常是基于2列的复合主键,其中一列是另一张表的外键)。

评论


算作fk_cluster吗?

– Kaji
2011年1月5日,下午5:51

#7 楼

我正在一个环境中工作,其中每个列名都以从表名派生的前缀开头,这不是我的发明,但是我对此很满意。

理想情况下,列名在整个过程中都是唯一的数据库中的所有表。

一些观察结果:


我们只需要表别名,当表在select语句中多次连接时
防止在复制代码段时出现一些错误,因为列名必须适合表名
它有助于显示外键列指向哪个表

一般思想:
大多数重要的是每种命名约定的一致性:
-单数与复数(适用于表而不是列)
-标识主键和外键(它们建立结构与数据库内容的关系)
-存储字符串和相同字符串的简短变体时要保持一致
-与标志,状态等保持一致。

#8 楼

我同意Spredzy的回答,但会补充一点,作为优先事项,我将使用camelCase而不是under_score。

firstName,lastName等。

评论


-1,因为CamelCase不适用于所有数据库系统,并且您未指定数据库系统。例如,在Oracle中使用CamelCase是个坏消息(它需要使用双引号来创建它,但是从那时起,访问它的每个人都必须跳过箍才能访问/使用它)。什么样的恶梦。

–ScottCher
2011年1月4日20:50

@ScottCher-我不知道它在Oracle中不起作用,但是我不是Oracle DBA。鉴于列名首先需要符合有关DBS制定的规则,我认为这是一个假设。

–托比
2011年4月20日在8:32

#9 楼

对于Oracle,您不希望将列名命名为'id'或'name'或任何通用名称。

问题在于,默认情况下,在较早版本中,Oracle将尝试基于在相似的列名上,因此,如果我对所有名称都进行了正确命名,那么我还最终在表之间指定了默认的join子句。

但是即使您没有使用Oracle,也不会选择出现在多个表中的名称,这也意味着您不必每次都要在两个表中进行选择时就不必经历别名的麻烦:

SELECT
  instrument.name as instrument_name,
  instrument.abbr as instrument_abbr,
  source.name     as source_name,
  source.abbr     as source_abbr,
  ...
FROM ...


因此,如果多表选择是常态,则较长的列名可以节省您的键入时间。 (如果您一次只使用一个表……您真的需要一个关系数据库吗?)

...并且保存类型使我们在Oracle中遇到另一个问题-至少在8i中(我上Oracle SQL调优和数据建模课程时的当前版本),执行计划的缓存仅基于查询的前几个字符(不记得确切的值... 1024?),因此如果您的查询在where子句的末尾仅因所有方式而有所不同,并且要提取的列很长,则可能会导致性能下降,因为它无法正确缓存执行计划。

Oracle有一个指南来选择他们认为是好的表和列名的指南,这基本上是删除字母的指南,直到大约5到8个字符,但我从不在乎。 br />
...

除此之外,


列总是单数(表总是复数)
所有名称均为小写,仅在cas中如果由于上述原因导致区分大小写
,请使用下划线代替驼峰式大小写。

update:对于不熟悉Oracle联接行为的用户,请参见精通Oracle的最后一个示例SQL:联接条件,其中提到:


发生了什么?原因在于,除了vendor_id之外,这两个表还有另一对具有相同名称的列。该列是名称。因此,当您要求在供应商表和零件表之间进行自然联接时,联接不仅通过将两个表的Supplier_id列相等,而且也将两个表中的name列相等而发生。由于没有供应商名称与该供应商的零件名称相同,因此查询不会返回任何行。


在“旧连接语法”(8i及更早版本)下,“ “自然联接”是默认的联接行为,如果您未指定联接条件,我相信仍然如此。一旦“ NATURAL JOIN”成为9i中的正式选项,一般建议不要使用它,因为糟糕的列命名会把您搞砸,这是我要提倡的好列名称。

评论


您在第二段中指的是“自然联接”吗?如果这样的话,那么......只要有可能,就应该指定希望数据库系统联接表的方式。将其留给数据库决定可能会产生意外/不一致的结果。此外,自然联接仅限于两个表之间的联接,因此其可用性相对有限。

–ScottCher
2011年1月4日21:30

NATURAL JOIN从来都不是默认值。如果没有给出显式联接,则将进行笛卡尔联接(即,表中的每一行都与另一表中的每一行联接)。在支持ANSI联接(即FROM子句中指定的联接)之前,必须在WHERE子句中进行联接。

–加里
2011年1月11日在4:42



-1用于自然连接。当不相关的架构更改可以中断连接,或者更糟的是,在不引起任何错误的情况下更改它们时,您将痛苦不堪。请考虑一下孩子,并且总是指定您的联接字段。

–万事通
2011年10月4日在21:16

@ScottCher:“由数据库决定” –首先,大概是指“ DBMS”而不是“数据库”。其次,Oracle中没有AI或拟人机制。相反,NATURAL JOIN是确定性的。

–有一天
2011-10-26 12:58



@Joe交叉联接过去,过去和将来始终是“默认值”。除非明确使用自然连接,否则Oracle从未匹配列名称

–杰克·道格拉斯(Jack Douglas)
2011-10-26 13:38



#10 楼


切勿使用双引号",因为这样做会覆盖数据库的本机大小写折叠。 SQL规范要求将所有标识符都折叠为大写。某些数据库(例如PostgreSQL)将它们折叠为小写形式。如果不加引号,则它将在所有数据库中都可用,并且它们可以将它们折叠为规范或特定于rdbms的默认值。
请使用under_score(_),因为如上所述,您不应该使用camelCase 。

{entity}_id用于ID(以及指向这些ID的外键)。因为那样您可以使用USING子句。连接条件中使用的全局唯一键名是规范中建立的约定。

SELECT *
FROM employee
INNER JOIN department
  USING (department_id);

  -- compare to
  ON employee.department_id = department.department_id;




评论


我将其更新为更加明确。

–埃文·卡洛尔(Evan Carroll)
18 Mar 27 '18 at 19:58