【问题标题】:sqlite database architecture - referencing multiple rowssqlite 数据库架构 - 引用多行
【发布时间】:2014-06-14 23:16:12
【问题描述】:

我有一张表 materials,其中包含(我正在使用 web2py):

materials_db.define_table('materials',
    Field('name','string'),
    Field('reference','string'),
    Field('manufacturer','string'),
    Field('date_added','date'),
    Field('density','double'), # Density - kg/m³
    Field('emissivity','double'),
    Field('specific_heat','double'), # Specific Heat - kJ/kg.K
    Field('thermal_conductivity','double') # Thermal conductivity - W/m.K
    )

我现在想创建一个表constructions。每个结构都是以有序方式组合任意数量的材料,例如像这样:

+------------+-------+
|  Material  | Layer |
+------------+-------+
| Concrete   |     1 |
| Airgap     |     2 |
| Insulation |     3 |
| Plaster    |     4 |
+------------+-------+

Layer 应该能够更改构造中材料的位置。建筑将具有新的属性,这些新属性将根据所用材料的属性和建筑内的位置进行计算。

我真的不知道如何去做。 layer 在构造中的值必须是唯一的,但显然在构造之间不能唯一,即每个构造都可以有一个值为 1 的层。

我是否需要为每个构造创建一个新表,然后在我的表 constructions 中引用所有这些表?这是我目前唯一模糊的想法,但这似乎不太正确......有没有好的方法?

【问题讨论】:

  • 刚刚在我的答案中添加了第三部分“将被计算的属性”。你想要那些在你的数据库中。从查询中获取它们。

标签: sql database-design relational-database


【解决方案1】:

我不熟悉 web2py,但纯粹从数据库的角度来看,您的模型应该如下所示:

  • 每个构造在 CONSTRUCTION 表中都有一行。
  • 每个材料在 MATERIAL 表中占一行。
  • BOM 中的每一行1 是 CONSTRUCTION_MATERIAL 表中的一行,通过 composite 键 {CONSTRUCTION_ID, LAYER} 标识。

换句话说,这是结构和材料之间的多对多关系,CONSTRUCTION_MATERIAL 表充当“连接”或“链接”表2。如有必要,您可以在联结表中添加“数量”等字段。


1 账单或材料。

2 尽管有点“不寻常”:MATERIAL_ID 不是允许在相同结构的不同层中使用相同材料的键的一部分。相反,如果相同的材质在每个构造中只能出现一次,则只需创建另一个复合键:{CONSTRUCTION_ID, MATERIAL_ID}。

【讨论】:

  • 像 TomCatt 一样,您误读了这个问题。问题的材料层图解表是给定结构的有序材料层。 pandita 与键(构造,级别)具有三元关系。任何其他建筑材料关系都没有实际意义。 pandita 还想要一个带有派生信息的基础;他们应该使用视图(或查询)。
  • @philipxy 在您上面的评论中,您是否有意使用:“relation”,然后是“relationship”,它们是不同的术语?无论如何,一种材料将具有相同的密度、热导率等......独立于它的使用位置,因此它必须在自己的表中,无论您以后如何决定继续表示建筑材料连接,或缓存派生数据或其他任何东西......
  • 1.在关系模型中,“关系”由关系/表表示。不理解它的方法则使用“关系”。所以我尝试使用“陈述”或“意义”,因为“谓词”太可怕了。只需阅读“关系”和“关系”的“表”。 2.重读问题:谓词/语句/意义/关系/关系是“CONSTRUCTIONS的级别LEVEL由MATERIAL制成”。键(C,L),FK(C),(M)。我没有以其他方式处理其他 C 或 M 或(明确)C-M 表/谓词。除非说派生这样不适合基地。
  • @philipxy 不,这些是不同的术语。 relation 是(在物理级别表示为)一个表。 RelationSHIP 可以是外键或联结表。 “关系模型”不是这样称呼的,因为表可以通过外键连接,而是因为表表示关系。除此之外,我不太了解您关于问题或答案的观点 - 需要改写吗?
  • 1.我知道 RM 之所以这样称呼是因为表/关系代表关系。关系有多种用途,我将其用作“实体-关系”的名称。 (不是作为联结/关联表本身,而是作为事物在以特定方式处于关系相关时所处的抽象事物。)不再赘述这里。 2. 我看错了你的 C_M 表。 (一排的两列扔了我。)同意你的设计。这是我发布的。我的评论/答案中的“CONSTRUCTIONS 的级别 LEVEL 由 MATERIAL 制成”是其特征谓词。
【解决方案2】:

你有两个名词:material 和 construction。任何材料项目都可以进入多种结构,任何结构都可以由多种材料组成。这是一个经典的多对多关系。名词成为保存在表格中的实体。交叉表定义了关系:

create table MatConst(
  MatID int not null, -- Foreign key to Material table
  ConstID int not null, -- Foreign key to Construction table
  Qty number not null,  -- The number, volume or weight of Mat in Const.
  primary key( MatID, ConstID )
);

这两个外键成为关系表的主键,因此对于正在构建的每个事物,只能有一个用于混凝土的条目,一个用于石膏的条目,依此类推。数量字段允许输入 57(磅混凝土)或 150(平方英尺石膏)等数量。当然,您可以根据需要添加描述关系的其他列。

【讨论】:

  • 感谢@TommCatt。如果我理解正确,我最终会得到三个表:materials 如上所述,constructions 将汇总并可能处理来自交叉表matconst 的信息。 matconst 中的每一行主要是 (MatID,ConstID),因此在计算特定结构的属性时(例如整体热导率、价格……),它会解析 matconst 表中的主键以查找包含我感兴趣的构造的 ID 的行。我理解正确吗?对不起,我显然是一个数据库菜鸟......
  • @pandita & TommCatt TommCatt 误读了这个问题。问题的材料层图解表是给定结构的有序材料层。 pandita 与键(构造,级别)具有三元关系。任何其他建筑材料关系都没有实际意义。 pandita 还想要一个带有派生信息的基础;它应该有一个视图(或查询)。
  • @padita:是的,你似乎很好地掌握了这个概念。从施工方查看时,在 ConstID 字段中找到该 ID 会显示该施工中使用的所有材料。从材质方面看,查找特定材质的 MatID 将找到所有使用该材质的结构。 @philipxy:是的,我看到了layer 属性,但没有立即理解它的含义,所以我把它留给了其他人。它可以像在 MatConst 中添加一个 layer 字段一样简单,成为 PK 的一部分。然后可以有一层灰泥、一层绝缘层、一层灰泥等。
【解决方案3】:

写下您需要描述应用情况的语句。

每个语句都给出一个表格。一个表包含使其陈述成立的行。

materials(material_id,name,...) // material [material_id] has name [name] and ...
constructions(construction_id,purpose,...) // construction [construction_id] is good for [purpose] and ...
construction_layers(construction_id,material_id,layer) // construction [construction_id] layer [layer] is [material_id]

将数据库限制在可能出现的状态。

只会出现一些应用情况。这些语句加上这些情况意味着只能出现一些数据库状态。告诉 DMBS,这样它就可以停止其他状态。在约束中说出来。

键(PK 和 UNIQUE 列集)表示基表的值受到约束。 FK 表示拖车表是相互约束的。

materials(material_id,name,...) // material [material_id] has name [name] and ...
    pk (material_id)
constructions(construction_id,purpose,...) // construction [construction_id] is good for [purpose] and ...
    pk (construction_id)
construction_layers(construction_id,material_id,layer) // construction [construction] layer [layer] is [material_id]
    pk (construction_id,layer)
    fk (construction_id) references constructions (construction_id)
    fk (material_id) references materials (material_id)

如果 DBMS 为每个 construction_layers 行提供就好了

CHECK(layer >= 1)

但如果没有特定 DBMS 的触发器,这可能会也可能不会。

我们还想检查每个构造的层是连续的(可能不是一直)。您必须通过当前 DBMS 下的触发器来执行此操作。

以某些方式限制您在声明中的发言。

除了键列之外,您应该在基表中拥有的唯一属性是作为整个键的函数的属性。 (这给出了一个 5NF 的表。)(计算列在任何时候都可以。)

不是从给定基表派生的其他信息应位于单独的基表中。

您想要的任何其他表都应该作为查询或视图获取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多