2013-11-11 2 views
2

У меня есть (упрощенная) схема базы данных, которая представляет card, card_sets и card_prints. Один card может быть представлен в нескольких card_sets. Действительная пара (card, card_set) называется card_print.Проектирование схемы РСУБД. Предъявление подмножества

Мне также необходимо смоделировать отношения card_have и card_want.

card_have должен иметь возможность выразить выражение «У меня есть эта карточка из определенного набора».

card_want должен быть в состоянии выразить оба следующих:

  1. «Я хочу эту карту, я не забочусь о множестве оно из.»
  2. «Я хочу эту карточку, я хочу, чтобы она была из наборов». (В качестве альтернативы, рассмотреть этот вариант проще этого:. «Я хочу эту карту, я только хочу, чтобы из этого набора»)

card_want сводится к тому, что составляет подмножество возможных card_prints в card.

Это то, что я до сих пор (немного упрощенным):

CREATE TABLE IF NOT EXISTS "card" 
    (id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , name TEXT  NOT NULL UNIQUE 
); 

CREATE TABLE IF NOT EXISTS "card_set" 
    (id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , name TEXT  NOT NULL UNIQUE 
); 

CREATE TABLE IF NOT EXISTS "card_print" 
    (id   BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , card_id  BIGINT  NOT NULL REFERENCES "card"(id) 
    , card_set_id BIGINT  NOT NULL REFERENCES "card_set"(id) 
); 

CREATE TABLE IF NOT EXISTS "card_have" 
    (id    BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , card_print_id BIGINT  NOT NULL REFERENCES "card_print"(id) 
); 

CREATE TABLE IF NOT EXISTS "card_want" 
    (id  BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
); 

CREATE TABLE IF NOT EXISTS "card_want_set" 
    (card_want_id BIGINT  NOT NULL REFERENCES "card_want"(id) 
    -- One the following two lines: 
    -- , card_print_id BIGINT NOT NULL REFERENCES "card_print"(id) 
    -- , card_set_id BIGINT NOT NULL REFERENCES "card_print"(id) 
); 

«Я не забочусь о наборе карты от» будет представлен не связывая любой card_print_id/card_set_id с card_want экземпляр.

Проблема этих решений заключается в том, что связанные card_print_id/card_set_id могут не соответствовать card_id. Это можно было бы немного облегчить, введя ограничения на card_print_id/card_set_id, но это все еще кажется немного неэлегантным и субоптимальным.

Решение проще вариант может выглядеть следующим образом:

CREATE TABLE IF NOT EXISTS "card_want" 
    (id  BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , card_id BIGINT  NOT NULL REFERENCES "card_print"(id) 
    , card_set_id BIGINT REFERENCES "card_set"(id) -- NULL means "I do not care about the set." 
); 

Он разделяет проблему решения сложнее варианта.

Есть ли лучший и более элегантный способ подойти к этой проблеме (либо более сложный, либо более простой вариант)?

Заранее спасибо.

ответ

2

Я думаю, что источником проблем является то, что вы разработали свои таблицы соединений с суррогатными первичными ключами (столбец идентификаторов).

Одним из недостатков использования суррогатного первичного ключа является disassociation:
Значения сгенерированных суррогатных ключей не имеют отношения к реальному значению данных, содержащихся в строке. При проверке строки, содержащей ссылку внешнего ключа на другую таблицу с использованием суррогатного ключа, значение строки суррогатного ключа не может быть распознано из самого ключа. Каждый внешний ключ должен быть соединен, чтобы увидеть соответствующий элемент данных.
Это может также затруднить проведение аудита, поскольку неверные данные не очевидны.

Так что я думаю, что если вы создадите свои таблицы с помощью не суррогатных ключей и при необходимости сможете использовать уникальные ключи, проблема может быть решена.

проект дизайн будет выглядеть так:

CREATE TABLE IF NOT EXISTS "card" 
    (id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , name TEXT  NOT NULL UNIQUE 
); 

CREATE TABLE IF NOT EXISTS "card_set" 
    (id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY 
    , name TEXT  NOT NULL UNIQUE 
); 

CREATE TABLE IF NOT EXISTS "card_print" -- (card_id + card_set_id) are the PRIMARY key 
    (card_id  BIGINT  NOT NULL REFERENCES "card"(id) PRIMARY KEY 
    , card_set_id BIGINT  NOT NULL REFERENCES "card_set"(id) PRIMARY KEY 
); 

CREATE TABLE IF NOT EXISTS "card_have" -- card_set_id + card_id is the PRIMARY KEY 
    (card_id  BIGINT  NOT NULL REFERENCES "card_print"(card_id) PRIMARY KEY 
    , card_set_id BIGINT  NOT NULL REFERENCES "card_print"(card_set_id) PRIMARY KEY  
); 

CREATE TABLE IF NOT EXISTS "card_want" -- card_id is the PRIMARY KEY 
    (card_id BIGSERIAL NOT NULL UNIQUE PRIMARY KEY REFERENCES "card(id)" 
); 

CREATE TABLE IF NOT EXISTS "card_want_set" (card_id + card_set_id) is the PRIMARY KEY 
    (card_id BIGSERIAL NOT NULL PRIMARY KEY REFERENCES "card_print(card_id)" 
    ,card_set_id BIGINT  NOT NULL PRIMARY REFERENCES "card_print"(card_set_id) 
); 
+0

Привет. Спасибо за ваш ответ. Я думаю, что это все еще имеет проблемы с выражением «Меня не волнует, из чего установлена ​​карта» (в отличие от «Я хочу, чтобы карта была из любого ** текущего набора **). Причина, по которой я дал каждому карточку распечатать идентификатор, заключается в том, что для каждой распечатки карты есть и официальный идентификатор, который я хочу сохранить в базе данных, поэтому я использовал его в качестве первичного ключа для таблицы «card_print». – TheCuriousOne

+0

Имея отношение к карточному столу в card-want, не удовлетворяет «Мне не важно, из чего установлена ​​карта»? –

Смежные вопросы