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


30

我曾经这样在数据库中标记列:

user_id
user_name
user_password_hash

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

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


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

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

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

@bernd_k:我已经添加了一些链接到我的答案,下面

Answers:


33

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

我建议您采用一种更自然的方法。

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

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

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


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

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

17

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


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

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

@glasnt明智的决定。
加里克2011年

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

9

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

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


7

我认为,在数据库模式中,每列在表之间应具有唯一的名称。这有几个原因:

  • 从建模的角度来看:首先从大量的属性开始,然后将其规范化为表格。随着时间的流逝,您可能会进一步规范化或规范化,或者引入视图或实例化视图,或者引入新表。如果所有列名都是唯一的,这将永远不是问题。

  • 您可以使用以下连接语法:a JOIN b USING (a_id) JOIN c USING (a_id)。非常方便,并有助于以下几点。

  • 如果您运行带有大量联接的查询或使用创建查询SELECT *,则您永远不会(或者可能很少)发生冲突。想想加盟person.nameproduct.namecountry.name,等Urgh。

  • 通常,如果您有大量查询,则很难跟踪id到处都意味着什么。


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

@Spredzy:我只会考虑冗余。
Peter Eisentraut 2011年

1
这些问题的答案是:别名。
所有行业的乔恩

7

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

USERS
----
id
username,
password
registration_date

我使用大写的表名。这使我可以轻松识别表格。我刚刚命名的列各代表其含义。我尽量不要使用数字或在其中包含任何前缀或后缀。这将使查询完全简单且非常简单。

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


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

5

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

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


4
算作fk_cluster吗?
卡吉

5

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

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

一些观察:

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

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


3

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

名字,姓氏等。


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

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

3

对于Oracle,您将不需要命名列“ id”或“ name”或任何通用名称。

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

但是,即使您使用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个字符,但是我从不在乎。

...

除此以外:

  • 列始终为单数(表始终为复数)
  • 所有名称均为小写,以防万一区分大小写
  • 由于上述原因,请使用下划线代替驼峰式大小写。

更新:对于不熟悉Oracle 联接行为的人员,请参阅“ 精通Oracle SQL:联接条件”的最后一个示例,其中提到:

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

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


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

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

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

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

1
@Joe cross join是,曾经且始终是“默认值”。甲骨文公司从来没有对列名的匹配,除非natural join被明确使用
杰克·道格拉斯

1
  1. 切勿使用双引号,"因为这样做会覆盖数据库的本机大小写折叠。SQL规范要求将所有标识符都折叠为大写。某些数据库(例如PostgreSQL)将它们折叠为小写形式。如果未引用任何内容,则它将在所有数据库中工作,并且它们可以将其折叠为规范或特定于rdbms的默认值。
  2. 请使用under_score(_),因为如上所述,您不应该使用camelCase。
  3. 使用{entity}_id的IDS(和外键指向这些IDS)。因为那样您可以使用该USING子句。连接条件中使用的全局唯一键名是规范中建立的约定。

    SELECT *
    FROM employee
    INNER JOIN department
      USING (department_id);
    
      -- compare to
      ON employee.department_id = department.department_id;

1
我对此进行了更明确的更新。
埃文·卡罗尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.