在数据库中建模1到1..n的关系

时间:2008-10-27 11:25:34

标签: database postgresql

你如何为宾客关系预订酒店房间(如果重要的话,在PostgreSQL中)?一个房间可以有几个客人,但至少有一个。

当然,可以将客人与使用外键booking_id的预订联系起来。但是,如何在DBMS级别强制执行一个房间必须至少有一个访客?

可能是不可能的?

6 个答案:

答案 0 :(得分:5)

实际上,如果您阅读了该问题,则说明已预订的酒店客房。这很容易做到如下:

Rooms:
    room_id primary key not null
    blah
    blah

Guests:
    guest_id primary key not null
    yada
    yada

BookedRooms:
    room_id primary key foreign key (Rooms:room_id)
    primary_guest_id foreign key (Guests:guest_id)

OtherGuestsInRooms:
    room_id foreign key (BookedRooms:room_id)
    guest_id foreign key (Guests:guest_id)

这样,当OtherGuests为0或更多关系时,您可以强制执行至少有一个访客的预订房间。没有客人,您无法创建预订的客房,如果没有预订的房间,您将无法添加其他客人。

如果你想要一个n对n的关系,你可以遵循这种逻辑,这种关系应该被归一化为一个单独的表,其中包含1对n和n对1的两个表。 / p>

答案 1 :(得分:4)

在这种情况下,我建议您正在建模的实体实际上是预订 - 一个实体 - 而不是房间和客人的两个实体。

所以表格就像

BOOKING
-------
booking id
room id
guest id (FK to table of guests for booking)
first date of occupancy
last date of occupancy

如果访客ID不可为空, 而且每次预订还有另一张桌子可以容纳客人...

GUESTS
------
guest id
customer id (FK to customer table)

答案 2 :(得分:1)

您可以将其中一个guest虚拟机指定为“主要”guest虚拟机,并将其映射到Rooms表上的列。当然,对于一家酒店来说,这是一个荒谬的规则,有一个房间有0位客人完全有效(我很可能支付一个房间,而不是留在那里)......

答案 3 :(得分:1)

我认为你的意思是房间预订至少是一位客人。 ANSI标准SQL允许您将约束表达为ASSERTION,如:

create assertion x as check
   (not exists (select * from booking b
                where not exists
                   (select * from booking_guest bg
                    where bg.booking_id = b.booking_id)));

但是,我不认为Postgres支持(我不确定任何当前的DBMS是否支持)。

有一种使用物化视图和检查约束的方法,但我从未在实践中看到过这种方法:

1)创建物化视图

select booking_id from booking b
where not exists 
   (select * from booking_guest bg 
    where bg.booking_id = b.booking_id);

2)向物化视图添加检查约束:

check (boooking_id is null)

如果物化视图不为空,即如果预订没有关联的访客,则此约束将失败。但是,您需要注意这种方法的性能。

答案 4 :(得分:0)

一个尚未出租的房间怎么样?您正在寻找的是预订,预订可能至少需要一位客人。

我认为您所询问的是,您是否可以保证不添加预订记录,除非您至少有一位客人,并且您无法在没有预订的情况下添加客人。对于大多数DBMS系统来说,它有点像Catch-22。

答案 5 :(得分:0)

我会说你应该用三个主键创建一个bookings表。但是,您可以参考beds表格,而不是参考预订房间。

bookings:
  bed_id: foreign_key primary
  guest_id: foreign_key primary
  day: date primary
  bill_id: foreign_key not null

beds:
  room_id: foreign_key primary

由于primary意味着需要,因为这是客人和房间相关的唯一方式,所以确保没有客人就无法预订。

请注意,只有一个day字段。这要求您为客人留在客房中的每一天创建预订,同时确保不会意外预订两次。在任何一天,只有一位顾客可以预订床位(房间不适用)

bill_id就在那里,您可以将预订转介到账单的特定记录中,也可以通过其他内容来参考,例如迷你吧费用。