Database design 数据库设计/建模问题-约束还是无约束?

Database design 数据库设计/建模问题-约束还是无约束?,database-design,normalizing,Database Design,Normalizing,鉴于以下结构: City Area User 每个地区只有一个城市。 每个用户至少有一个但可能有多个区域。 每个用户都有一个城市,而且只有一个城市 最优雅的建模方式是什么 目前,我有: User, UserArea, Area, City 其中UserArea与用户的关系为1:M,Area与城市的关系为1:1 问题是: 在当前模型下,用户可以有3个或4个区域,但其中2个区域可能位于城市“1”中,其他2个区域可能位于城市“2”中。这违反了商业规则 我是应该设置一个约束来防止这种事情发生,还是一

鉴于以下结构:

City
Area
User
每个地区只有一个城市。
每个用户至少有一个但可能有多个区域。
每个用户都有一个城市,而且只有一个城市

最优雅的建模方式是什么

目前,我有:

User,
UserArea,
Area,
City
其中UserArea与用户的关系为1:M,Area与城市的关系为1:1

问题是:

在当前模型下,用户可以有3个或4个区域,但其中2个区域可能位于城市“1”中,其他2个区域可能位于城市“2”中。这违反了商业规则

我是应该设置一个约束来防止这种事情发生,还是一个更好的方法来进一步规范化,这样就不可能出现这种悖论?如果是,如何对该系统建模,以便:

1个用户=1个城市
1个区域=1个城市
1个用户=M个区域


感谢您的见解。

我将为用户、地区和城市分别创建一个表,然后创建第四个表,其中包含用户(FK)、城市(FK)和地区(FK)列,其中用户和城市(组合)被限制为唯一。然后,每当插入用户区域组合时,它将不允许非唯一的城市。

我将为每个用户、区域和城市创建一个表,然后创建第四个表,其中包含User(FK)、Cities(FK)和Area(FK)列,其中Users和Cities(组合)被约束为唯一。然后,每当插入用户区组合时,它将不允许非唯一的城市。

我唯一能想到的是:

为面积表指定一个CityID和AreaID的复合备用键。使AreaID为主(这样它只能有一个城市)

使用此备用键(AK1)在Area和UserArea之间形成FK关系

为用户表提供UserID和CityID的复合备用键。将用户标识设为主要

使用此备用键(AK2)在用户和用户区域之间形成FK关系

因此,您的UserArea表如下所示:

用户ID 城市ID 面积


基于AK2的外键将强制您选择与用户所在城市匹配的城市,基于AK1的外键将强制您选择属于该城市的区域。本质上,AK1和AK2外键将重叠,强制执行您想要的操作。

我唯一能想到的是:

为面积表指定一个CityID和AreaID的复合备用键。使AreaID为主(这样它只能有一个城市)

使用此备用键(AK1)在Area和UserArea之间形成FK关系

为用户表提供UserID和CityID的复合备用键。将用户标识设为主要

使用此备用键(AK2)在用户和用户区域之间形成FK关系

因此,您的UserArea表如下所示:

用户ID 城市ID 面积


基于AK2的外键将强制您选择与用户所在城市匹配的城市,基于AK1的外键将强制您选择属于该城市的区域。本质上,AK1和AK2外键将重叠,强制执行您想要的操作。

我认为您的“用户、用户区域、区域、城市”方法是正确的。依靠约束和业务逻辑来防止违规行为。

我认为您的“用户、用户区域、区域、城市”方法是正确的。依靠约束和业务逻辑来防止违规行为。

您能提供关于什么是区域的更多详细信息吗?让我陈述我的假设:
用户住在城市里
每个城市都有区域。
一个地区只能归入一个城市。
用户只能居住在一个城市
考虑到这些条件,您的设计规范中似乎存在以下功能依赖关系:
地区->城市
用户->城市
您的商业模式表明,用户可以在同一个城市中拥有多个地址,但不能在两个不同的城市中拥有一个地址。这是一个现实的设计约束吗?如果我可以有多个地址,为什么不在不同的城市呢

如果要存储给定用户的所有区域,则需要第三个表(如您所建议的)。该表看起来像
UserArea(userID,AreaID)。您需要使用触发器或存储过程来实现业务逻辑。

您可以提供关于什么是区域的更多详细信息吗?让我陈述我的假设:
用户住在城市里
每个城市都有区域。
一个地区只能归入一个城市。
用户只能居住在一个城市
考虑到这些条件,您的设计规范中似乎存在以下功能依赖关系:
地区->城市
用户->城市
您的商业模式表明,用户可以在同一个城市中拥有多个地址,但不能在两个不同的城市中拥有一个地址。这是一个现实的设计约束吗?如果我可以有多个地址,为什么不在不同的城市呢

如果要存储给定用户的所有区域,则需要第三个表(如您所建议的)。该表看起来像
UserArea(userID,AreaID)。您需要使用触发器或存储过程实现业务逻辑。

USER\u AREAS
只需要以下列:

  • USER\u ID
    (pk,fk用于
    用户。USER\u ID
  • AREA\u ID
    (pk,fk表示
    AREA.AREA\u ID
区域与区域表中的一个城市关联;通过从区域表中向上滚动,您可以知道哪些城市与用户关联:

区域

  • 区域ID
    (主键)
  • CITY-ID
    (fk代表
    CITY.CITY\u ID
CITY\u ID
放在
USER\u area
表中是多余的。其次,将
CITY\u ID
放在
USER\u AREA
表中并不保证该记录中的
AREA\u ID
实际上与AREA表中的
CITY\u ID
相关联。CHECK约束仅通过限制列接受的值来强制域完整性,并且不能执行
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])