Вопрос проектирования / моделирования базы данных - Ограничения или Их отсутствие?

StackOverflow https://stackoverflow.com/questions/1155058

  •  18-09-2019
  •  | 
  •  

Вопрос

Учитывая следующую структуру:

City
Area
User

В каждой Области есть 1 и только 1 Город.
У каждого пользователя есть по крайней мере одна, но, возможно, и несколько Областей.
У каждого Пользователя есть 1 и только 1 Город.

Какой самый элегантный способ смоделировать это?

В настоящее время у меня есть:

User,
UserArea,
Area,
City

Где UserArea - это соотношение 1: M с Пользователем, а Area - 1: 1 с Городом.

Проблема заключается вот в чем:

В текущей модели у пользователя может быть 3 или 4 Области, но 2 из этих областей могут находиться в городе "1", а остальные 2 области могут находиться в городе "2".Это нарушение бизнес-правил.

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

1 Пользователь = 1 Город;
1 Район = 1 Город;
1 Пользователь = M Областей;

Спасибо вам за понимание.

Это было полезно?

Решение 7

Этот ответ был предоставлен мне от SQLServerCentral, и он делает именно то, что я искал. Существует избыточность (как указал Рексум на этом форуме), но нет возможности аномолей.

Я очень заинтересован в ваших комментариях и предложениях.


CREATE TABLE [dbo].[Cities](
    [CityID] [int] IDENTITY(1,1) NOT NULL,
  [CityName] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Cities] PRIMARY KEY CLUSTERED
(
   [CityID] ASC
)
)
CREATE TABLE [dbo].[Users](
   [UserID] [int] IDENTITY(1,1) NOT NULL,
  [UserName] [varchar](50) NOT NULL,
  [CityID] [int] NOT NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
  [UserID] ASC
)
)

ALTER TABLE [dbo].[Users]  WITH CHECK ADD  CONSTRAINT [FK_Users_Cities] FOREIGN KEY([CityID])
REFERENCES [dbo].[Cities] ([CityID])
GO
ALTER TABLE [dbo].[Users] CHECK CONSTRAINT [FK_Users_Cities]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_UsersCity] ON [dbo].[Users]
(
   [UserID] ASC,
   [CityID] ASC
)

CREATE TABLE [dbo].[Areas](
    [AreaID] [int] IDENTITY(1,1) NOT NULL,
  [AreaName] [varchar](50) NOT NULL,
  [CityID] [int] NOT NULL,
 CONSTRAINT [PK_Areas] PRIMARY KEY CLUSTERED
(
  [AreaID] ASC
))


GO
ALTER TABLE [dbo].[Areas]  WITH CHECK ADD  CONSTRAINT [FK_Areas_Cities] FOREIGN KEY([CityID])
REFERENCES [dbo].[Cities] ([CityID])
GO
ALTER TABLE [dbo].[Areas] CHECK CONSTRAINT [FK_Areas_Cities]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_AreasCity] ON [dbo].[Areas]
(
 [AreaID] ASC,
   [CityID] ASC
)
GO
CREATE TABLE [dbo].[UserCityArea](
   [UserID] [int] NOT NULL,
    [CityID] [int] NOT NULL,
    [AreaID] [int] NOT NULL,
 CONSTRAINT [PK_UserCityArea] PRIMARY KEY CLUSTERED
(
   [UserID] ASC,
   [CityID] ASC,
   [AreaID] ASC
)
)

GO
ALTER TABLE [dbo].[UserCityArea]  WITH CHECK ADD FOREIGN KEY([UserID], [CityID])
REFERENCES [dbo].[Users] ([UserID], [CityID])
GO
ALTER TABLE [dbo].[UserCityArea]  WITH CHECK ADD FOREIGN KEY([AreaID], [CityID])
REFERENCES [dbo].[Areas] ([AreaID], [CityID])

Другие советы

У меня была бы таблица для каждого пользователя, области и города, затем была бы четвертая таблица со столбцами User (FK), Cities (FK) и Areas (FK), где Users & Cities (в сочетании) ограничены уникальностью.Затем всякий раз, когда вставляется комбинация пользовательского региона, она не допускает использования неуникального города.

Единственное, что я могу придумать, - это:

Дайте таблице площади композитный альтернативный ключ из CityId и AreaId. Сделайте Areaid Primary (так что он может иметь только один город).

Используйте этот альтернативный ключ (AK1), чтобы сформировать отношения FK между области и пользователя.

Дайте пользователю таблицу композитного альтернативного ключа пользователя и CityId. Сделайте пользовательский иид.

Используйте этот альтернативный ключ (AK2), чтобы сформировать отношение FK между пользователем и пользователем.

Так что ваша таблица пользователя будет выглядеть так:

UserId CityId

Иностранный ключ на базе AK2 заставит вас выбрать город, который соответствует родному городу пользователя, а иностранный ключ из AK1 заставит вас выбрать область, которая принадлежит этому городу. По сути, иностранные ключи AK1 и AK2 будут перекрываться, вынуждая то, что вы хотите.

Я думаю, что ваш подход «Пользователь, пользователь, область, город» верен. Полагайтесь на ограничения и бизнес -логику, чтобы предотвратить нарушения.

Можете ли вы предоставить более подробную информацию о том, что такое область? Позвольте мне указать мои предположения:
Пользователь живет в городе.
В каждом городе есть районы.
Район может упасть только в один город.
Пользователь может жить только в одном городе
Учитывая эти условия, у вас, кажется, есть следующие функциональные зависимости в своей спецификации дизайна:
Район -> Город
Пользователь -> Город
Ваша бизнес -модель предполагает, что пользователь может иметь несколько адресов в одном городе, но не может иметь адрес в двух разных городах. Это реалистичное ограничение дизайна? Если я могу иметь несколько адресов, то почему не в разных городах?
Если вы хотите сохранить все области данного пользователя, вам нужна третья таблица (как вы предложили). Таблица будет выглядеть как
Userarea (userid, areaid). Вам необходимо внедрить бизнес -логику, используя триггер или хранимую процедуру.

USER_AREAS Требуются только следующие столбцы:

  • USER_ID (PK, FK для USERS.USER_ID)
  • AREA_ID (PK, FK для AREA.AREA_ID)

Район связан с одним городом в таблице районов; Вы знаете, какие города ассоциируются с пользователем, свернувшись из таблицы областей:

AREA

  • AREA_ID (PK)
  • CITY-ID (FK для CITY.CITY_ID)

Поставка CITY_ID в USER_AREAS Таблица избыточно. Во -вторых, размещение CITY_ID в USER_AREAS Таблица не гарантирует, что AREA_ID в этой записи фактически связан с CITY_ID в столе. Ограничение проверки только обеспечивает соблюдение целостности домена, ограничивая значения, которые приняты столбцом, и не могут ссылки на столбцы в других таблицах, должны меньше определенной пользовательской функции.

Вы не можете обеспечить соблюдение делового правила областей пользователя, принадлежащих только одному городу в базе данных. Это должно было быть сделано на уровне приложения (любой Sproc управляет вставкой/обновлением USER_AREAS стол).

Я не уверен, что вы имеете в виду под «областями».

Я полагаю, что городское подразделение выглядит следующим образом:

У планеты есть страны. В стране есть регионы (штаты, провинции и т. Д.) Районы (города, города, деревни и т. Д.).

User => страна + регион/район + город ( + район)

Не могли бы вы уточнить области?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top