可能包含其他相同实体的实体的数据库设计

时间:2016-08-06 08:54:56

标签: mysql foreign-keys composite

我有一些运动设施,可以在其中进行5x5足球比赛。我正在尝试为他们制作一个简单的预订系统。 我的问题是,一些字段组合并创建更大的字段,设施的管理层希望将它们视为自己的实体(如果他们预订它们就是这样,为什么不呢)。

让我们举一个实际的例子。 我们有设施std::string。他们有3个5x5字段,一个接一个,然后打电话给FA,其中任意两个可以组合成一个7x7字段,让我们称它为sa, sb, sc,所有三个字段组成一个10x10字段,让我们打电话它dd。 其他设施也会发生这种情况,但这是更极端的情况。

我一直在努力思考如何在预订和处理时对字段的表进行建模,但我不确定。

我的一个解决方案是为字段提供表格

te

他和另一张桌子有一对一或零关系

CREATE TABLE IF NOT EXISTS field (
    id              SMALLINT(5) UNSIGNED    NOT NULL AUTO_INCREMENT,
    arena_id        SMALLINT(4) UNSIGNED    NOT NULL,
    internal_id     TINYINT(3) UNSIGNED     NOT NULL,
    is_composite    BOOLEAN                 NOT NULL DEFAULT FALSE,

    PRIMARY KEY (id),
    UNIQUE (arena_id, internal_id),

    CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE
)
;

将包含包含组件字段的字段的条目。仅当CREATE TABLE IF NOT EXISTS field_component ( field_id SMALLINT(5) UNSIGNED NOT NULL, component SMALLINT(5) UNSIGNED NOT NULL, PRIMARY KEY (field_id, component), CONSTRAINT fk_field_component_field_id FOREIGN KEY (field_id) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_field_component_field_id2 FOREIGN KEY (component) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE ) ; 表中的标志is_composite为真时,才会存在条目。

一个更简单的解决方案我认为这是一个更多的手动,而不是有第二个表和标志,只有一个字符串列,我把字段的id,使复合字段以逗号分隔列表。

另外,我正在考虑将标志移动到第三个名为field的表,我可能与该字段有一对一的关系,并且将包含有关每个字段的信息。即尺寸,地面材料,如果它是复合材料,还有它的注释等。

任何思想建议,批评,替代方案都是受欢迎的。

1 个答案:

答案 0 :(得分:1)

我会考虑以下内容,确保在复合表field_component中,子和复合竞技场至少是相同的。请注意,InnoDB检查约束不会强制执行。

第1点:is_composite以下的field_component质量隐含地指向真正是复合的东西的field_component未被强制执行。它可能有更多的合成(意味着更多的表)。

第2点:在这个阶段或者可能永远不应该将数据类型过度设计成小而小的INT。特别是如果是mysql的新手。

第3点:FK关系倾向于在子表中不存在时自动为您创建KEYS。我们在show create table中明确具有的唯一键有效地用于两个目的。它强制执行非dupe,并且它用作生成FK自动生成器的索引。另一个是自动生成的,如CREATE TABLE IF NOT EXISTS field ( id SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT, arena_id SMALLINT(4) UNSIGNED NOT NULL, internal_id TINYINT(3) UNSIGNED NOT NULL, is_composite BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (id), UNIQUE (arena_id, internal_id), CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS field_component ( field_id SMALLINT(5) UNSIGNED NOT NULL, component SMALLINT(5) UNSIGNED NOT NULL, PRIMARY KEY (field_id, component), CONSTRAINT fk_field_component_field_id FOREIGN KEY (field_id) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_field_component_field_id2 FOREIGN KEY (component) REFERENCES field(id) ON UPDATE CASCADE ON DELETE CASCADE ); TweakA: CREATE SCHEMA TweakA; USE TweakA; -- drop table arena CREATE TABLE IF NOT EXISTS arena ( id INT PRIMARY KEY, aName varchar(200) NOT NULL ); -- drop table field CREATE TABLE IF NOT EXISTS field ( id INT AUTO_INCREMENT PRIMARY KEY, arena_id INT NOT NULL, -- like the Arena # internal_id INT NOT NULL, -- 1, 2, 3 for the field # is_composite BOOLEAN NOT NULL DEFAULT FALSE, friendly_name VARCHAR(100) NOT NULL, UNIQUE KEY (arena_id, internal_id), CONSTRAINT fk_field_arena_id FOREIGN KEY (arena_id) REFERENCES arena(id) ON UPDATE CASCADE ON DELETE CASCADE ); -- drop table field_component CREATE TABLE IF NOT EXISTS field_component ( id INT AUTO_INCREMENT PRIMARY KEY, arena_id INT NOT NULL, child_internal_id INT NOT NULL, composite_internal_id INT NOT NULL, -- The following UK will pick up part of what I will explain in the Narrative UNIQUE KEY `unq_arena_comp_child` (arena_id,child_internal_id,composite_internal_id), CONSTRAINT fk_field_child_field_id FOREIGN KEY (arena_id,child_internal_id) REFERENCES field(arena_id, internal_id) ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT fk_field_composite_field_id FOREIGN KEY (arena_id,composite_internal_id) REFERENCES field(arena_id, internal_id) ON UPDATE CASCADE ON DELETE CASCADE -- note that InnoDB check constraints are not effective ); -- Note, look at output from the following -- show create table field_component; -- this shows the auto-gen of 1 key due to FK -- -- The following block is a Helper block during testing -- Truncate in reverse order: -- TRUNCATE TABLE field_component; -- TRUNCATE TABLE field; -- TRUNCATE TABLE arena; -- test data load: INSERT arena(id,aName) VALUES (1,'Boston Arena, North Shore'); INSERT field(arena_id,internal_id,is_composite,friendly_name) VALUES (1,1,FALSE,'sa'), (1,2,FALSE,'sb'), (1,3,FALSE,'sc'), (1,4,TRUE,'dab'), (1,5,TRUE,'dac'), (1,6,TRUE,'dbc'), (1,7,TRUE,'abc'); INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES (1,1,4), (1,2,4), (1,1,5), (1,3,5), (1,2,6), (1,3,6), (1,1,7), (1,2,7), (1,3,7); -- SUCCESS INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES (2,2,4); -- will fail, as expected INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES (1,72,4); -- will fail, as expected INSERT field_component(arena_id,child_internal_id,composite_internal_id) VALUES (1,1,444); -- will fail, as expected show create table field_component; -- the above will exhibit the AUTO_INCREMENT gap anomoly due to the above -- expected failed inserts, setting AI=13 or so DROP SCHEMA TweakA; 中所示。因此,我们的UNIQUE KEY在那里有一些用途。

<div class="row">
  <<div class="col-md-5">    
    <div class="left">
      <img>
    </div>
    <div class="right">
      <h1>
      some text
      </h1>
    </div>
  </div>  

  <<div class="col-md-5">    
    <div class="left">
      <img>
    </div>
    <div class="right">
      <h1>
      some text
      </h1>
    </div>
  </div>   
</div>

我写了一个FK Enforces Composite Relationship的答案,有点复杂。您可以根据您要查找的数据库强制执行级别走这条路线。

另请参阅第3点中提到的由于FK关系而导致的KEYS自动生成的MySQL Using FOREIGN KEY Constraints

因此,当您通过执法工作时,这个答案可能会继续增长。或者做客户端。如果是我,我会做DB强制执行。

无论如何,如评论中所述,不要将CSV值存储在列中。