给定以下结构:

City
Area
User

每个区域都有1个城市和1个城市。
每个用户至少有一个但可能多个区域。
每个用户只有1个城市和1个城市。

建模最优雅的方式是什么?

目前,我有:

User,
UserArea,
Area,
City

userarea是1:m的关系,用户与城市的区域为1:1。

问题是:

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

我是否应该只是制定一个限制来防止这种事情,或者是进一步归一化的更好方法,以使这种类型的悖论不可能?如果是这样,如何建模该系统:

1用户= 1个城市;
1区= 1个城市;
1用户= m区域;

感谢您的见解。

有帮助吗?

解决方案 7

This answer was provided to me from SQLServerCentral, and it does exactly what I was looking for. There is a redundancy (as rexum pointed out in this forum), but there is no possibility of anomolies.

I'm very interested in your comments and suggestions.


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])

其他提示

我将为用户,区域和城市提供每个表格,然后有一个带有列用户(FK),城市(FK)和区域(FK)的第四个表,其中用户和城市(组合)约束为唯一。然后,每当插入用户区域组合时,它都不会允许一个非唯一的城市。

我唯一能想到的是:

给区域桌是CityID和Areaid的复合替代钥匙。使apeariD初级(因此只能有一个城市)。

使用此备用密钥(AK1)在区域和UserArea之间形成FK关系。

给用户表作为用户ID和CityID的复合替代键。使UserId primary。

使用此备用密钥(AK2)在用户和用户区之间形成FK关系。

因此,您的Userarea表看起来像这样:

Userid CityID apeard

基于AK2的外国钥匙将迫使您选择与用户家乡相匹配的城市,而基于AK1的外国钥匙将迫使您挑选属于该城市的区域。本质上,AK1和AK2外国钥匙将重叠,迫使您想要的东西。

I think that your "User, UserArea, Area, City" approach is correct. Rely on the constraints and business logic to prevent violations.

Can you provide more details on what is an area? Let me state my assumptions:
User lives in a city.
Every city has areas.
An area can fall into one city only.
A user can live in one city only
Given these conditions, you seem to have the following functional dependencies in your design spec:
Area -> City
User -> City
Your business model suggests that the user can have multiple addresses within the same city but cannot have an address in two different cities. Is this a realistic design constraint? If i can have multiple addresses, why not in different cities then?
If you want to store all the areas of a given user you need a third table (like you have suggested). The table would look like
UserArea(userID,AreaID). You need to implement the business logic using a trigger or a stored procedure.

USER_AREAS only requires the following columns:

  • USER_ID (pk, fk for USERS.USER_ID)
  • AREA_ID (pk, fk for AREA.AREA_ID)

An area is associated to one city in the AREAS table; you know which cities are associated with the user by rolling up from the AREAS table:

AREA

  • AREA_ID (pk)
  • CITY-ID (fk for CITY.CITY_ID)

Putting CITY_ID in the USER_AREAS table is redundant. Secondly, placing CITY_ID in the USER_AREAS table does not guarantee that the AREA_ID in that record is actually associated with the CITY_ID in the AREA table. A CHECK constraint only enforces domain integrity by limiting the values that are accepted by a column, and can not reference columns in other tables must less a user defined function.

You can't enforce the business rule of a user's areas only ever belonging to a single city in the database. It would have to be done at the application level (whatever sproc manages inserting/updating the USER_AREAS table).

I'm not sure what you mean by "areas".

I believe the urban division is as follows:

The planet has countries. A country has regions (states, provinces etc.) Regions have areas (cities, towns, villages etc.) Areas (if big enough) can have districts.

User => Country + Region/Area + City (+ District)

Could you please elaborate on areas?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top