У меня есть база данных с тремя таблицами, назовите их Sale
, Store
и Hub
. Каждый экземпляр Store
ссылается на экземпляр Hub
, хотя могут быть экземпляры Hub
, на которые нет ссылок в таблице Store
. В большинстве случаев экземпляр Sale
будет ссылаться на экземпляр Store
(и, следовательно, может отображаться на экземпляр Hub
.) Однако в некоторых случаях Sale
будет напрямую ссылаться на таблицу Hub
.
Это отношение моделирует следующее: магазины снабжены хабами (магазины и хабы - оба местоположения), и хотя большинство продаж происходит в магазинах, они также могут происходить в хабах.
В упрощенной версии, где отношения Sale
- Hub
не существуют, я легко могу сделать StoreID
частью первичного ключа для таблицы Sale
, что я и сделаюкак здесь, за исключением того, что StoreID
иногда будет нулевым (когда продажа происходит в хабе, а не в магазине).
Поэтому пример из таблицы Sale
может выглядеть следующим образом:
SaleID SaleDate StoreID HubID Quantity
1 2012-05-16 1 NULL 100
2 2014-09-27 2 NULL 99
3 2018-02-01 NULL 9 30
4 2019-11-12 17 NULL 207
Таблицы Store
и Hub
будут содержать информацию о местонахождении вместе с некоторыми полями, относящимися к магазину и концентратору.
Проблема заключается в том, как справиться с созданием хорошего альтернативного ключа для Sale
таблица (SaleID
- мой суррогатный первичный ключ.) Теоретически продажа должна определяться датой и местоположением. Однако у меня есть два поля местоположения, и они оба обнуляются. Мне интересно, могу ли я справиться с этим, используя уникальные индексы? Или я могу как-то использовать контрольные ограничения? Или промежуточная таблица местоположений?
Кроме того, предположим, что у меня также есть таблица SuperHub
(представьте, Hub
означает SuperHub
, что Store
означает Hub
.) Если я хочу добавить SuperHubID
поле к моей Sale
таблице, как это повлияет на вещи? С 3+ пустыми полями не проверять ограничения / уникальные индексы начинают выходить из-под контроля?
Здесь потенциально может выглядеть ERD для этого:
Редактировать: Чтобы уточнить, я пытаюсь понятьлучший способ включить информацию о местоположении как часть альтернативного ключа для таблицы Sale
, учитывая, что «информация о местоположении» разделена между несколькими различными таблицами (первичный ключ для таблицы Sale
- это просто суррогатный ключ SaleID
.) Попытка включить все таблицы расположений в альтернативном ключе приводит к появлению пустых значений в ключе (см. Пример из таблицы Sale
выше.) Как лучше всего решить эту проблему?
Редактировать 2: Хорошо, вот еще несколько уточнений. Я включаю определения таблиц и т. Д.
--Table Defs
CREATE TABLE Sale (
SaleID int NOT NULL IDENTITY(1, 1),
SaleDate date NOT NULL,
StoreID int NULL,
HubID int NULL,
Quantity int NOT NULL);
-- StoreID and HubID are nullable since a sale can occur at one or the other
-- Is there a better way to organize this?
-- @PeterHe mentioned Category/Subcategory model
CREATE TABLE Store (
StoreID int NOT NULL IDENTITY(1, 1),
StoreNumber int NOT NULL,
Customer nvarchar(20) NOT NULL,
Address nvarchar(50) NOT NULL,
HubID int NOT NULL);
CREATE TABLE Hub (
HubID int NOT NULL IDENTITY(1, 1),
HubNumber int NOT NULL,
Customer nvarchar(20) NOT NULL,
Address nvarchar(50) NOT NULL);
--PKs
ALTER TABLE Sale
ADD CONSTRAINT PK_Sale PRIMARY KEY CLUSTERED (SaleID);
ALTER TABLE Store
ADD CONSTRAINT PK_Store PRIMARY KEY CLUSTERED (StoreID);
ALTER TABLE Hub
ADD CONSTRAINT PK_Hub PRIMARY KEY CLUSTERED (HubID);
--FKs
ALTER TABLE Sale
ADD CONSTRAINT FK_Sale_Store
FOREIGN KEY (StoreID) REFERENCES Store (StoreID)
ON UPDATE NO ACTION
ON DELETE NO ACTION;
ALTER TABLE Sale
ADD CONSTRAINT FK_Sale_Hub
FOREIGN KEY (HubID) REFERENCES Hub (HubID)
ON UPDATE NO ACTION
ON DELETE NO ACTION;
ALTER TABLE Store
ADD CONSTRAINT FK_Store_Hub
FOREIGN KEY (HubID) REFERENCES Hub (HubID)
ON UPDATE NO ACTION
ON DELETE NO ACTION;
--AKs
ALTER TABLE Store
ADD CONSTRAINT AK_Store UNIQUE (StoreNumber, Customer);
ALTER TABLE Hub
ADD CONSTRAINT AK_Hub UNIQUE (HubNumber, Customer);
ALTER TABLE Sale
ADD CONSTRAINT AK_Sale UNIQUE (SaleDate, StoreID, HubID);
--issue here is StoreID and HubID are nullable since sale could occur at either