2008-10-27 7 views
3

Comment modéliseriez-vous la relation entre la chambre d'hôtel et les invités (dans PostgreSQL, si c'est important)? Une salle peut avoir plusieurs invités, mais au moins un.Modélisation d'une relation 1 à 1..n dans la base de données

Bien sûr, on peut relier les clients aux réservations avec une clé étrangère booking_id. Mais comment appliquez-vous au niveau du SGBD qu'une pièce doit avoir au moins un invité?

Peut-être que c'est juste impossible?

+0

Vous devez avoir un hôtel très efficace s'il n'a jamais de chambres vides. –

+0

Voici les chambres réservées –

+0

Votre design ... Il y a quelque chose qui ne va pas. – Will

Répondre

5

En fait, si vous lire la question, il indique les chambres d'hôtel réservées. Ceci est assez facile à faire comme suit:

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) 

De cette façon, vous pouvez appliquer une chambre réservée ayant au moins un invité alors que les OtherGuests est un 0 ou plus-relation. Vous ne pouvez pas créer une salle réservée sans un invité et vous ne pouvez pas ajouter d'autres invités sans la salle réservée.

C'est le même type de logique que vous suivez si vous voulez une relation n-à-n, qui devrait être normalisée à une table distincte contenant un 1-à-n et un n-à-1 avec les deux tables.

0

Qu'en est-il d'une chambre qui n'a pas été louée? Ce que vous cherchez sont des réservations et une réservation a probablement besoin d'au moins un invité.

Je pense que vous demandez si vous pouvez garantir qu'un enregistrement de réservation n'est pas ajouté, sauf si vous avez au moins un invité et que vous ne pouvez pas ajouter un invité sans réservation. C'est un peu un Catch-22 pour la plupart des systèmes de SGBD.

1

Vous pouvez désigner l'un des invités comme invité «principal» et l'associer à une colonne de la table Pièces. Bien sûr, c'est une règle ridicule pour un hôtel, où il est parfaitement valable d'avoir une chambre avec 0 invités (je pourrais très bien payer une chambre et ne pas rester là) ...

+0

Il parle de chambres réservées - c'est distinct des chambres. – paxdiablo

+0

Vrai, mais les hôtels ne documentent pas vraiment qui est dans les chambres, ils documentent qui paie pour les chambres. Et les hôtels ont également un contact principal pour leurs réservations afin qu'ils sachent qui contacter quand le chèque rebondit ... –

4

Dans ce contexte, je suggère que l'entité que vous modélisez est en fait une BOOKING - une seule entité - plutôt que deux entités de chambre et d'invité.

Donc, la table serait quelque chose comme

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

Où guest id est pas annulable, et vous avez une autre table pour tenir les clients par réservation ...

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

Ceci est une bien meilleure façon de le regarder. –

1

Je pense que ce que vous voulez dire, c'est qu'une chambre réservée est pour au moins un invité. ANSI SQL standard vous permettra d'exprimer la contrainte comme quelque chose comme AFFIRMATION:

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

Cependant, je ne pense pas que Postgres soutient que (je ne suis pas sûr que tout SGBD courant ne).

Il est un moyen utilisant des vues matérialisées et les contraintes de vérification, mais je ne l'ai jamais vu cela dans la pratique:

1) Créer une vue matérialisée comme

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

2) Ajouter une contrainte de vérification à la vue matérialisée:

check (boooking_id is null) 

Cette contrainte échouera si jamais la vue matérialisée est pas vide, à savoir s'il y a une réservation sans invité associé. Cependant, vous devrez faire attention à la performance de cette approche.

0

Je dirais que vous devriez créer une table bookings avec trois clés primaires. Mais au lieu de faire référence aux salles de réservation, vous pouvez vous référer à une table 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 

Depuis que l'primary implique d'être nécessaire, et puisque c'est la seule façon un invité et une salle peuvent être liés, il est sûr qu'il ne peut y avoir une réservation sans un invité.

Notez qu'il n'existe qu'un seul champ day. Cela nécessite que vous créiez une réservation pour chaque jour où un invité séjournera dans une chambre, mais aussi que rien ne sera accidentellement réservé deux fois. Un lit peut être réservé par un seul client un jour donné (ce qui n'est pas le cas pour les chambres)

Le bill_id est là pour que vous puissiez référencer une réservation à un enregistrement spécifique pour une facture, qui peut également être référencée par d'autres choses comme les frais de minibar.

Questions connexes