Вопрос

Let's suppose I have an CustomerOrder table and a RentalEquipment table.

A customer is able to rent one of the RentalEquipment and that unique rental equipment is recorded within the CustomerOrder.

Since the relationship is 1:1 (for a customer to rent 2 equipments, 2 orders must be made), which of both should contain the foreign key?

Consider the following:

  1. A customer may return a rental equipment, so it will be available to another customer's order anytime in the future.
Это было полезно?

Решение

Well, consider this. Does a RentalEquipment contain a CustomerOrder, or does a CustomerOrder contain a RentalEquipment?

My guess is that it's the latter, unless you have a very odd system.

Given that, a CustomerOrder should contain a reference to the RentalEquipment it contains. You can have a status flag on the CustomerOrder indicating whether the order is still open, or the RentalEquipment has been returned.

This also makes sense if you want to track the order history of a given RentalEquipment.

If it's a foreign key in CustomerOrder, you can look through your CustomerOrders to find the history. If you put the relationship in RentalEquipment, you'll only have information about the CurrentOrder. Also, when the customer returns it, you'll have to update the RentalEquipment record and set the FK to null. Messy.

Другие советы

What I would do is create a separate table for the relationship between customer orders and rental equipment - let's call it CustomerRental and this would have two columns for each foreign key and a composite primary key made up of each key. This way each row for a customer or order could be modified independently without worrying about breaking the relationship(s) between them.

In the case of a return I would suggest creating another table to capture this idea let's call it CustomerRentalStatus which maps many:1 to RentalStatus. Programmatically what this lets you do is validate the rental status of the order e.g. "Received", "Dispatched", "Delivered", "Returned" and you can have a modified date column to check when the status was last updated.

Of course you might not want to normalize your solution this far yet depending on the needs of your application (yagni) in which case you could just have a column in the Orders table to capture the status of the order

This is not actually 1:1.

Same piece of equipment can be rented to multiple customers and same customer can rent multiple pieces of equipment, as long as that's done at different times...

  1. So its actually M:N, over the lifetime of the database.
  2. However, it is 1:1 within a particular period of time.

So you need to represent the (1) through a junction table and find a way to enforce the (2).

Consider the following model:

enter image description here

[From, To] is the time period of renting.

  • The UNIQUE constraint {CustomerId, From} ensures a customer cannot start renting (same or different equipment) twice at the same time.
  • The UNIQUE constraint {RentalEquipmentId, From} ensures a piece of equipment cannot start to be rented (to same or different customer) twice at the same time.

Unfortunately, both constraints work only on moments in time and neither guarantees there will be no overlaps of time periods (in other words: they don't take To into account). You'll need to find a way to prevent the overlap of time period [From, To] for any given CustomerId (and the same for any given RentalEquipmentId).

If you are lucky, your DBMS can do that for you (see exclusion constraint under PostgreSQL). Otherwise, you can enforce it with a trigger (but be careful to lock properly, to avoid race conditions).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top