我正在开发一个大数据库,从这种情况来看,我决定至少考虑两次关于表格和字段布局的决策。我最关心的是主键。
我几乎总是使用table name
加_id
来命名这些索引。我这样做是因为在连接表时我不必担心重复的字段名称,因为 Delphi 数据库组件将字段设为table_name.field_name
,而只是字段。
另一方面,如果我们可以为每个表使用相同的ID字段名称,那么创建一个函数来处理与该索引控件有关的每个表总是更容易。
是否有人在选择其中一个数据库设计时遇到了错误的经验?在每个字段名称上重复表名称是一种好方法吗?
答案 0 :(得分:22)
我过去设计了许多数据库,并且错误地不止一次地命名表和列。我知道其他人有different opinions,但这些是我现在遵循的规则:
表格名称为复数
我很自然地拥有一个products
表而不是product
表,特别是在选择语法时:SELECT whatever FROM products
感觉比SELECT whatever FROM product
好。最后,如果您选择单数或复数,则无关紧要,只要您不混合它们。
字段名称是单数
同样,这是一个或多或少随意的选择,但对我来说似乎很自然,也是大多数人使用的。 (你可以说SELECT descriptions FROM products
更有意义,但嘿,你不能争论什么呢?
所有名称均为小写,并使用下划线分隔单词
有些人使用Pascal样式大小写,例如ProductId
甚至JavaScript样式productId
。我个人曾经使用过许多不同的数据库引擎,说实话,我不能不记得哪些是区分大小写的,哪些不是。 table_name
似乎被普遍接受,我从来没有遇到任何问题。由于您专门为Delphi应用程序设计数据库,因此您可能希望选择Pascal样式,以便源代码不会混合使用不同的样式。我个人只是坚持field_name
。 (顺便说一句:即使某些数据库允许使用标识符中的特殊字符,我也会像瘟疫一样避免使用它们,对于可能是数据库关键字的列名也是如此。即使我为表制造商设计了数据库,我也会从不将产品表命名为“tables”)
主键和外键包括表名
products
表获得product_id
主键。无论其他表链接到哪一个都获得product_id
外键。这会自动记录数据库设计的一部分,并允许使用自然连接。我之前设计了一个数据库,每个表都有一个标记为“id”的主键。那确实非常混乱。
其他列的表名不是前缀
这可能就是这个列表上的规则我偶尔会打破一次,但首先要做的事情。根据此规则,产品的说明将进入description
字段,而不进入product_description
。造成这种情况的主要原因是代码中的混乱程度较低。查询变得更短,更易于阅读。 SELECT product_id, description, price FROM products WHERE price>1 AND price<9
比SELECT product_id, product_description, product_price FROM products WHERE product_price>1 AND product_price<9
更容易阅读。两个查询都会做同样的事情,但是一个查询比另一个更多。
我有时会违反这条规则有三个原因:
a。对于主键。参见#4 - 能够看到哪些列是什么不是杂乱的主键,但重要的是每次都写下来。
b。当两个完全不同的值类型共享相同的标识符时:一个人的名字与产品名称完全不同。在开发的某些阶段,它可以更轻松地区分person_name
和product_name
,而无需交付大量元数据。 (或者,就此而言,在人的name
和产品的brand_name
之间,这消除了对表格前缀的需要。)
c。如果两个包含相同字段名称的表可能经常在查询中加入。如果您有产品description
和订单description
,则可能需要重新命名查询的列,这可能很麻烦。
同样,以上所有都是个人偏好。你的旅费可能会改变。唯一似乎普遍认同的是:选择一种风格并坚持下去。
P.S。我可能没有回答你的部分问题,但“......创建一个函数来处理与索引控件有关的每个表总是更容易。”对我毫无意义。
答案 1 :(得分:2)
我认为这主要是个人偏好以及您喜欢和何时打字的数量。将所有字段名称键入为table_name.field_name
,这样您就可以在SELECT *
语句中执行join
而无需在重复的字段名称上使用表名进行资格预审,这看起来好像很多在前面打字几次字段可能需要预先评定,如果你的大多数select语句都包含字段名称,那么只需输入table_name.field_name
字段就好像打字一样。
我确信添加更长的字段名称具有无关紧要的性能问题,并且可能只有在通过网络传输架构信息以用于ODBC但仍然不是真正的问题时才会非常明显。
我不知道 Delphi ,但在 .NET 中,您也可以按位置查找字段名称,或者访问标记为主键字段的字段所以我不确定一个函数参数是否有效,要求表具有相同的ID字段名称。
我总是在我的表中保留我的主键字段UID
,而不是在字段名称声明中包含表名,除了必须预先UID
字段选择之前我从未遇到过问题多个表中的语句。虽然我可以看到包含tablename.UID
关键字段的一些好处,因为跨多个表的许多SELECT *
语句将没有重复的字段错误,除非其他表中存在重复数据(我希望不会。)
答案 2 :(得分:1)
还需要考虑的另一件事是数据库建模。诸如ERwin,Visio等工具会自动将父PRIMARY KEY向下迁移到关系中,因此如果该字段在父表中加前缀,则无需在子 1 中重命名该字段。由于没有重命名,也没有人会忘记这样做的危险,只要看一下该字段的名称就可以让您自信地看到它来自哪里,而不需要在视觉上遵循与该字段来源的关系。当存在多个关系级别并使ER图更具可读性时,这一点尤为重要,IMO。
它还使SQL更清晰,因为我的大脑不需要“解析”别名来找出哪个字段来自哪里,并且使NATURAL加入的危险性稍差 2 < / sup>,但其他人对此可能有不同意见......
1 如果您使用parent.id
和child.id
,则必须将迁移的密钥重新定位到child.parent_id
之类,以避免命名冲突。但是,如果您使用parent.parent_id
和child.child_id
,则无需执行任何操作 - 迁移的密钥会自动命名为child.parent_id
。该链继续grandchild.grandchild_id
等...
2 通过诚实地说,如果你可以帮助它,你永远不应该做自然 - 总是明确指定你的加入标准。
答案 3 :(得分:0)
在delphi中,您也可以使用别名来解决重复名称字段的问题。
请参阅:
SELECT table1.fieldX AS 'myDesiredName', table2.fieldX AS 'myDesidedName2' FROM ...
这解决了ClientdataSets
o对象查询中重复名称的问题。
您的Delphi应用程序使用您在myDesiredName