Mysql 数据库设计。请问如何处理这个问题?

Mysql 数据库设计。请问如何处理这个问题?,mysql,database-design,Mysql,Database Design,我正在设计一个数据库(MySQL),用于管理车队 该公司在整个城市有许多车库,在每个车库,车辆得到维修(运营)。一个操作可以是3种服务中的任意一种 桌上车辆、桌上Garagae、桌上操作、桌上操作类型1、桌上操作类型2、桌上操作类型3 每个操作都有车辆ID、车库ID,但如何根据用户选择的服务类型将其链接到其他表(服务表) 我还想添加一个计费表,但我不知道如何设计这些表之间的关系。如果我完全理解,我建议这样做(首先,您不应该有三个操作表): 您需要六张桌子: vechicle: id, ... g

我正在设计一个数据库(MySQL),用于管理车队

该公司在整个城市有许多车库,在每个车库,车辆得到维修(运营)。一个操作可以是3种服务中的任意一种

桌上车辆、桌上Garagae、桌上操作、桌上操作类型1、桌上操作类型2、桌上操作类型3

每个操作都有车辆ID、车库ID,但如何根据用户选择的服务类型将其链接到其他表(服务表)


我还想添加一个计费表,但我不知道如何设计这些表之间的关系。

如果我完全理解,我建议这样做(首先,您不应该有三个操作表):

您需要六张桌子:

vechicle: id, ...
garage: id, ...

operation: id, vechicle_id, garage_id, operation_type (which can be 
one of the tree options/operations available, with the possibility to be extended)

customer: id, ...

billing: id, customer_id, total_amount
billingoperation: id, billing_id, operation_id, item_amount

您绝对不应该为操作创建三个表。在将来,如果您想引入一个新的操作,该操作将涉及在数据库中创建一个新表。

请注意,我不同意所有人说您不应该有多个操作表。我认为那很好,只要做得好。事实上,我现在正在用我的一个产品做这件事

如果我理解的话,在你问题的核心,你在问如何做表继承,因为Op类型1和Op类型2(等等)是一个操作。简而言之,你不能。较长的答案是,你不能…至少没有一些辅助逻辑

我假设您有某种程序可以从数据库中提取数据,而不仅仅是手工编写sql命令。在这种假设下,让我们将其用作数据库的子集:

Garage
------
GarageId | GarageLocation | etc. 
---------|----------------|------
1        | 123 Main St.   | XX   

Operation
---------
OperationId | GarageId | TimeStarted | TimeEnded | OperationTypeDescId | OperationTypeId 
------------|----------|-------------|-----------|---------------------|----------------
2           | 1        | noon        | NULL      | 2                   | 2


OperationTypeDesc
-------------
OperationTypeDescId | Name  | Description
--------------------|-------|-------------------------
1                   | OpFoo | Do things with the stuff
2                   | OpBar | Do stuff with the things


OpFoo
-----
OpID | Thing1 | Thing2
-----|--------|-------
1    | 123    | abc

OpBar
-----
OpID | Stuff1 | Stuff2
-----|--------|-------
1    | 456    | def
2    | 789    | ghi
使用此设置,您可以获得以下信息:

  • 车库有它的信息,简单明了
  • 一个操作有一个唯一的ID(OperationId)、一个执行它的车库、一个引用操作描述的ID和OperationType ID(稍后将对此进行详细介绍)
  • 操作类型的预填充表。每种类型都有一个唯一的ID(OperationTypeDescId)、操作的名称以及该操作的可读描述
  • OperationTypeDesc中每行1个表。为方便起见,表名应与名称列相同
现在我们可以开始了解继承在哪里发挥作用。在操作表中,
OperationTypeId
引用相关表的
OpId
。“相关表”由OperationTypeDescId确定

例如:假设我们有上述数据集。在本例中,我们知道在Main St 123的一个车库中发生了一次操作。我们知道该操作从中午开始,但尚未结束。我们知道操作类型为“OpBar”。因为我们知道我们正在执行OpBar操作而不是OpFoo操作,所以我们只能关注与OpBar相关的属性,即stuff1和stuff2。由于操作的OperationTypeId为2,我们知道Stuff1为789,Stuff2为ghi

现在是棘手的部分。在您的程序中,这将需要
反射
。如果你不知道那是什么,那就是从该类型的名称中获取
类型的做法。在我们的示例中,我们知道要查看哪个表(OpBar),因为它的名称在OperationTypeDesc表中。换句话说,你不会自动知道要查看哪个表;反思告诉你这些信息

编辑: Csaba说“将来,如果您想引入一个新的操作,该操作将涉及在数据库中创建一个新表”。这是正确的。您还需要向OperationTypeDesc表中添加新行。Csaba暗示这是一件坏事,我不同意——有几个条款。如果你要经常添加一个新的操作类型,那么是的,他提出了一个非常好的观点。您不希望不断地创建新表。但是,如果您提前知道将执行哪些类型的操作,并且很少添加新类型的操作,那么我认为这是一条路。所有操作共有的所有信息都会出现在操作表中,所有操作特定信息都会出现在相关的“子表”中


关于这一点,还有一点非常重要。因为这是如何设计的,你,人类,必须意识到设计。无论何时创建新的操作类型,都不像创建新表那么简单。具体来说,您必须确保新表名和OperationTypeDesc“name”条目相同。可以将其视为一个额外的约束-一个“整数”列只能包含整数,否则db将不允许数据。同样,“Name”列只能包含现有表的名称。您必须知道该约束,因为它不能(轻松地)自动执行。

但根据操作的不同,可能会有与该op.id相关的不同信息,因为字段名是SQL反模式。一些开发人员认为它是反模式…;)请解释“哪一个可以是可用的树选项之一,有可能被扩展”,以及您如何存储特定于这些单独操作的信息?您不需要一个包含所有可能操作的所有可能列的大型表。您可以添加另一个表:带有id的operationattribute、operation\u id、。。。三表方法的主要问题是它不可伸缩。如果要为所有操作生成一些统计信息,必须进行三次查询。
Garage
------
GarageId | GarageLocation | etc. 
---------|----------------|------
1        | 123 Main St.   | XX   

Operation
---------
OperationId | GarageId | TimeStarted | TimeEnded | OperationTypeDescId | OperationTypeId 
------------|----------|-------------|-----------|---------------------|----------------
2           | 1        | noon        | NULL      | 2                   | 2


OperationTypeDesc
-------------
OperationTypeDescId | Name  | Description
--------------------|-------|-------------------------
1                   | OpFoo | Do things with the stuff
2                   | OpBar | Do stuff with the things


OpFoo
-----
OpID | Thing1 | Thing2
-----|--------|-------
1    | 123    | abc

OpBar
-----
OpID | Stuff1 | Stuff2
-----|--------|-------
1    | 456    | def
2    | 789    | ghi