我有一些运动设施,可以在其中进行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
的表,我可能与该字段有一对一的关系,并且将包含有关每个字段的信息。即尺寸,地面材料,如果它是复合材料,还有它的注释等。
任何思想建议,批评,替代方案都是受欢迎的。
答案 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值存储在列中。