2016-08-06 27 views
0

Ich habe einige Sportanlagen, die Felder haben, in denen man 5x5 Fußball spielen kann. Ich versuche, ein einfaches Reservierungssystem für sie zu machen. Mein Problem ist, dass einige Felder kombinieren und größere Felder machen, die die Verwaltung der Einrichtungen als ihre eigenen Entitäten behandeln möchte (macht Sinn, wenn sie sie so buchen, warum nicht).Datenbank-Design für eine Entität, die aus anderen Entitäten bestehen könnte

Lassen Sie uns ein aktuelles Beispiel geben. Wir haben Anlage FA. Sie haben 3 5x5 Felder nebeneinander, nennen wir dann sa, sb, sc und zwei von ihnen können kombinieren, um ein 7x7 Feld zu machen, nennen wir es dd und alle drei, um ein 10x10 Feld zu machen, nennen wir es te. Dies passiert auch bei den anderen Einrichtungen, aber dies ist der extremste Fall.

Ich habe versucht zu denken, wie man die Tabellen für die Felder modelliert, wenn ich die Reservierung mache und damit umgehe, aber ich bin nicht sicher.

Eine Lösung, die ich habe, ist eine Tabelle zu haben, für die Felder

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 
) 
; 

Und theh hat eine Eins-zu Eins oder Null Beziehung mit einem anderen Tisch

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 

) 
; 

, die Einträge mit den Feldern haben die ein Komponentenfeld umfassen. Ein Eintrag existiert nur dann, wenn das Flag is_composite in der Tabelle field wahr ist.

Eine einfachere Lösung Ich dachte, dass ist ein bisschen mehr manuell, war statt der zweiten Tabelle und der Flagge, nur eine Zeichenfolge Spalte, wo ich die IDs der Felder, die das zusammengesetzte Feld als Komma machen getrennte Liste.

In einer separaten Notiz, ich habe darüber nachgedacht, die Flagge zu einer dritten Tabelle mit der Bezeichnung field_info zusammengesetzt zu verschieben, die ich eins zu eins Beziehung mit dem Feld haben könnte und Informationen über jedes Feld enthalten wird. d. h. Größe, Material des Bodens, wenn es zusammengesetzt ist oder nicht, Anmerkungen dazu etc.

Alle Gedankenvorschläge, Kritik, Alternativen sind willkommen.

+0

Was ist 'Feld_Komponente'? – Drew

+0

@Drew Sorry, schlechte Benennung. Unter der Annahme, dass die IDs für die Felder "sa", "sb", "sc", "dd" und "te" jeweils 1, 2, 3, 4 und 5 für das "te" -Feld wären, gäbe es drei Einträge in der field_component Tabelle (5, 1), (5,2), (5,3). Das ist das Feld 5 hat als Komponenten die Felder 1, 2 und 3 –

+0

nur einige offensichtliche Tippfehler nichts Material – Drew

Antwort

1

Ich würde Folgendes berücksichtigen, das in der zusammengesetzten Tabelle field_component gewährleistet, dass das Kind und Composite-Arenen mindestens gleich sind. Beachten Sie, dass InnoDB-Prüfbedingungen nicht erzwungen werden.

Punkt # 1: Die is_composite Qualität im Folgenden für die field_component implizit zurück zu etwas, das ist wirklich ein Composite ist nicht erzwungen. Es könnte mit mehr Compositing (mehr Tabellen) sein.

Punkt # 2: Die Datentypen sollten in diesem Stadium oder vielleicht überhaupt nicht in kleine und winzige INTs überentwickelt werden. Besonders wenn es neu für mysql ist.

Punkt # 3: Die FK-Beziehungen haben die Tendenz, KEYS für Sie automatisch zu erstellen, wenn sie nicht in der untergeordneten Tabelle vorhanden sind. Der eindeutige Schlüssel, den wir explizit in field_component haben, erfüllt effektiv zwei Zwecke. Es erzwingt Nicht-Duplikate und dient als der Index, der verwendet wird, wenn ein FK-Auto-Gen erzeugt worden wäre. Ein anderer wird automatisch generiert, wie in show create table zu sehen ist. Also, unser EINZIGARTIGER SCHLÜSSEL dient dort einigen Zwecken.

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; 

Ich schrieb eine FK Enforces Composite Relationship Antwort, die ein wenig kompliziert bekam. Je nachdem, auf welcher Ebene der DB Enforcement Sie sich befinden, können Sie diese Route wählen.

Siehe auch die Using FOREIGN KEY Constraints betreffend Auto-gen von KEYS aufgrund von FK-Beziehungen wie in Punkt # 3 erwähnt.

Also, diese Antwort könnte einfach weiter wachsen, während Sie durch die Durchsetzung arbeiten. Oder tun Sie es Client-Seite. Wenn ich es wäre, würde ich es tun DB Enforcement.

Unabhängig davon, wie in den Kommentaren erwähnt, speichern Sie keine CSV-Werte in einer Spalte.

+0

Danke. Für alle Informationen, die du mir gegeben hast. Ich denke, manchmal fällt es einem Entwickler schwer, aus der DB-Perspektive zu denken. Es ist einfacher, nur an eine programmatische Route zu denken. Ich schätze Ihre Hilfe. Ich hatte eine ähnliche Konklusion erreicht, aber alle zusätzlichen Informationen und Kommentare werden definitiv dazu beitragen, einige Dinge zu klären. –