Sql 数据库关系多对多3向混淆
我有一个简单的数据库a,我想创建一个预订和日程安排系统。它是开放的改变,以达到我的目标,所以不要担心改变设计,如果需要的话 以下是ERD: 问题如下: 我有一些成员可以在特定时间(预订期)预订特定地点(可预订区域)。当前关系集允许许多成员在多个地点多次预订,这些可能会重叠。i、 e.允许双重预订或同时预订两个位置(即同时在两个位置) 我的问题是,如何修改此数据库的设计,以严格允许以下内容: 会员只能预订一个地点,但可以多次预订(即9-9:30、9:30-10、10-10:30等)。有效地允许会员预订一个地点和时间。一旦预订,其他会员不得预订相同的地点和时间。他们可以在不同的时间预订相同的地点,也可以在相同的时间预订不同的地点,但不能同时预订两者 要实现这一点,我需要改变什么。我更喜欢在关系中这样做,只是因为这让它变得显而易见,然而,作为最后的手段,如果没有办法用关系来做,我会求助于触发器,但我不想使用它们,因为它们不像erd那么明显 提前感谢您的帮助 编辑1:触发器和检查约束确实是可接受的答案,我并不是说这不是标准或不正确。如果这是我能做到的唯一方法,那么我只能这样做。然而,我之所以这样问,是因为我更愿意让其他程序员尽可能清楚地认识到这一点,这就是为什么我在寻找一种通过关系来实现这一点的方法。然而,我承认这可能是不可能的。我只是不确定,回答这个问题Sql 数据库关系多对多3向混淆,sql,sql-server,database,sql-server-2008,relational-database,Sql,Sql Server,Database,Sql Server 2008,Relational Database,我有一个简单的数据库a,我想创建一个预订和日程安排系统。它是开放的改变,以达到我的目标,所以不要担心改变设计,如果需要的话 以下是ERD: 问题如下: 我有一些成员可以在特定时间(预订期)预订特定地点(可预订区域)。当前关系集允许许多成员在多个地点多次预订,这些可能会重叠。i、 e.允许双重预订或同时预订两个位置(即同时在两个位置) 我的问题是,如何修改此数据库的设计,以严格允许以下内容: 会员只能预订一个地点,但可以多次预订(即9-9:30、9:30-10、10-10:30等)。有效地允许会
编辑2:我知道我说过我想在不使用约束或触发器的情况下完成这项工作,但是如果没有extream措施(这将使事情变得过于复杂),似乎不可能完成这项工作。然而,我确实喜欢这个过于复杂的答案,因为它展示了一些关于人际关系的真正美好的想法。谢谢大家。原始回复 如果我理解正确,下面的场景显示了哪些是允许的,哪些是不允许的
Member Book Time Book Place
-----------------------------------------------------
John 0900-1000 Room 1
John 1000-1100 Room 1
John 1100-1200 Room 1
John 0900-1000 Room 2 <--- not allowed, member double booked
Jane 0900-1000 Room 1 <--- not allowed, room double booked
好的,在你写我之前,请听我说完!您的图表包含这些表的4/6。我建议将会员、预订时间和预订地点之间的关系分开
下面有一个代理主键和一个复合唯一键,以保证一段时间内没有成员被双重预订
Member_BookTime
---------------
ID (PK)
Member_ID (CUK)
BookTime_ID (CUK)
BookPlace_BookTime_ID
------------------
ID (PK)
BookPlace_ID (CUK)
BookTime_ID (CUK)
下面有一个代理主键和一个复合唯一键,以保证一段时间内没有房间被重复预订
Member_BookTime
---------------
ID (PK)
Member_ID (CUK)
BookTime_ID (CUK)
BookPlace_BookTime_ID
------------------
ID (PK)
BookPlace_ID (CUK)
BookTime_ID (CUK)
下面有一个复合主键,以及会员预订时间和房间预订时间之间的关系,以最终将会员与房间绑定到特定时间
Member_BookTime_BookTime_BookPlace
----------------------------------
Member_BookTime_ID (CPK)
BookPlace_BookTime_ID (CPK)
这些有什么意义吗?在上面的模式中,成员不能双重预订,房间不能双重预订。我意识到这可能是“过度规范化”,但它使关系更加清晰
建议的约束并不是真正的“隐藏”,因为它们显示在用于定义表的SQL中。我知道您希望使数据约束的所有内容从ERD可见,但有时约束太复杂。如果您只希望支持30或15分钟的间隔,我们可以执行以下操作 periods表如下所示:
ID StartPeriod End Period
1 0:00 0:15
2 0:15 0:30
3 0:30 0:45
4 0:45 1:00
5 1:00 1:15
*诸如此类
因此,如果您希望会员1在2012年7月30日午夜至凌晨12:30预订区域1,并提供“睡眠”的预订描述,则记录如下所示
BookingInfo
Id Description
1 "Sleep"
Bookings
Id MemberId PeriodID BookingInfoId BookableAreaId Day
1 1 1 1 1 7/30/2012
2 1 2 1 1 7/30/2012
然后,您可以在预订上放置两个唯一的索引,一个是MemberId、Day、PeriodId(这将防止它们被安排在同一时间的同一天)
一个用于BookableAreaId、Day、PeriodId(这将防止有人在同一天以相同的15分钟间隔重复预订同一区域)
您还可以删除Id字段作为Bookings表上的主键,并用这些字段上的主键替换其中一个唯一索引
很抱歉,格式不清晰,我是这个网站的新手。将ERD附加为链接,因为我无法发布图片(直到我获得足够的代表)我会像这样更改您的数据模型: BookingPeriods将包含一个时间段列表。例如您可以在上午和下午预订,即上午9点开始,下午1点结束。或以一小时为单位,即记录上午9点至10点、上午10点至11点等
Create table BookingPeriods (
id int primary key
, StartTime Time
, EndTime Time
, Description varchar(max)
)
BookingAvailability是时间段和日期之间的简单映射。因此,您有一个每个日期的列表,其中可以列出时间段
Create table BookingAvailability(
id int primary key
, Day Date
, PeriodId int references BookingPeriods(id)
constraint uq_bookingAvailability unique (Day, PeriodId)
)
BookableAreas只是一个物理位置列表
Create table BookableAreas(
id int primary key
, Name varchar(100)
, ActivityTypeId int
, Description varchar(max)
)
成员保持不变
Create table Members(
id int primary key
, FirstName varchar(100)
, ...
)
然后,预订就变成了一张桌子,一切都集中在一起。您可以为每个可用性记录和区域创建一个唯一的记录。memberid只是记录的一些辅助信息
Create table Bookings(
id int primary key
, AvailabilityId int references BookingAvailability(id)
, AreaId int references BookableAreas(id)
, MemberId int references Members(id)
constraint uq_Bookings unique (AvailabilityId, AreaId)
)
该数据模型将按如下方式使用:
请确保不要在此处的时段中注册“重叠”。例如,如果您想要更细粒度的细节,您需要每小时创建一个记录
INSERT INTO BookingPeriods (id, StartTime, EndTime, Description)
VALUES (1, '9:00 AM', '12:00 AM', 'Morning'),
(2, '1:00 PM', '4:00 PM', 'Afternoon')
这是您可以预订的可能时间段列表。(例如,不包括周末的日期)
这里我们尝试创建实际预订
INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (1, 3, 1, 1) -- Barak books the ground floor on 20120801 in the morning
INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (2, 3, 1, 2) -- Tony books the ground floor on 20120801 in the morning --> error
INSERT INTO Bookings(id, AvailabilityId, AreaId, MemberId)
VALUES (2, 4, 1, 2) -- Tony books the ground floor on 20120801 in the afternoon --> ok
你的建议是正确的。为了澄清,您是否建议我在bookings.bookingperiodid和bookings.bookableareaid上放置唯一键,然后添加一个单独的主键来标识每个预订。如果是的话,你确定这会满足我的要求吗。同样,唯一关键点本质上是隐藏约束的另一种形式。我并不反对,但我宁愿不使用。但是,如果没有其他选项