Нормализация таблиц SQL: простой вопрос об ограничении участия записей в отношении многих ко многим - PullRequest
1 голос
/ 21 октября 2010

Если у вас есть следующие таблицы и отношения:

  • Таблица продуктов
  • Таблица цен (одна или несколько цен на продукт)
  • Таблица версий (группы товаров, продаваемых в одном регионе)

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

Чтобы проиллюстрировать ограничение, у меня есть продукт по цене $ 1, $ 2 и $ 3. У меня есть медиа-зоны A, B, C, D, E, F, G, H, I (каждая представляет такое место, как Columbus OH)

product A price $1 goes to A, B, C
product A price $2 goes to D, E, F
product A price $3 goes to G, H, I

Продукт Цена $ 1, когда она существует в A, B, C, не может иметь других цен ($ 2, $ 3) в A, B, C

Будет ли таблица версии M2M преобразована в PricePoints, а затем будет помещен уникальный индекс в таблицу M2M для всех полей минус работа поля PricePoint? (подумал об этом, печатая это) Есть ли лучший способ представить отношения?

Ответы [ 3 ]

2 голосов
/ 21 октября 2010

У меня небольшие проблемы с пониманием вашего вопроса.Я не понимаю утверждения «Продукт Цена $ 1, когда она существует в A, B, C, не может существовать в D, E, F, G, H, I.».Ради этого ответа я предполагаю, что «версия» и «медиа-зона» - это одно и то же.

Используйте промежуточную таблицу цен с тремя полями: product_id, version_id и price_id.Первичный ключ этой таблицы (или уникальный индекс, если вы решите использовать инкрементный неинтеллектуальный ключ): (product_id, version_id).

1 голос
/ 21 октября 2010

Вот как я построил бы таблицы, чтобы отразить ограничения на основе предоставленных данных:

SQL DDL:

CREATE TABLE Products
(
 product_name CHAR(1) NOT NULL UNIQUE
);

CREATE TABLE ProductPrices
(
 product_name CHAR(1) NOT NULL
    REFERENCES Products (product_name), 
 product_price DECIMAL(19, 4) NOT NULL
    CHECK (product_price > 0), 
 UNIQUE (product_name,  product_price)
);

CREATE TABLE MediaZones
(
 zone_name CHAR(1) NOT NULL UNIQUE
);

CREATE TABLE Versions
(
 product_name CHAR(1) NOT NULL, 
 product_price DECIMAL(19, 4) NOT NULL, 
 FOREIGN KEY (product_name,  product_price)
    REFERENCES ProductPrices (product_name,  product_price), 
 zone_name CHAR(1) NOT NULL 
    REFERENCES MediaZones (zone_name), 
 UNIQUE (product_name, zone_name)
);

SQL DML (успешно = хорошо):

INSERT INTO Products (product_name) VALUES ('A');

INSERT INTO MediaZones (zone_name) 
   VALUES ('A'), ('B'), ('C'), 
          ('D'), ('E'), ('F'), 
          ('G'), ('H'), ('I');


INSERT INTO ProductPrices (product_name, product_price) 
   VALUES ('A', 1),
          ('A', 2), 
          ('A', 3);

SQL DML (неудачно = хорошо):

INSERT INTO Versions (product_name, product_price, zone_name) 
   VALUES ('A', 1, 'G');

INSERT INTO Versions (product_name, product_price, zone_name) 
   VALUES ('A', 1, 'A');

INSERT INTO Versions (product_name, product_price, zone_name) 
   VALUES ('A', 1, 'Z');
 INTO Versions (product_name, product_price, zone_name) 
   VALUES ('A', 2, 'A');

etc etc 
0 голосов
/ 21 октября 2010

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

...