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
只需要以下列:
(pk,fk用于USER\u ID
)用户。USER\u ID
(pk,fk表示AREA\u ID
)AREA.AREA\u ID
区域
(主键)区域ID
(fk代表CITY-ID
)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])