I've made a project that's essentially an online bookstore where one can buy books and place the order.
My database contains various tables like:
user
user_shipping_address
user_payment_mode
user_order
order_shipping_address
order_billing_address
order_payment_details
I tried to construct the EERD diagram for this but I am confused about one thing: A user_order
can only have one shipping address. I've created a foreign key order_id
in the order_shipping_address
table that references the primary key order.id
. I also have a shipping_address_id
foreign key in the table order
that references order_shipping_address.id
.
When I try to generate the ER diagram, it gives me two different relationships. A 1:1 relationship between the order
and the shipping address and a 1:M relationship from the shipping address to the order. I don't know how to structure the foreign key constraints because I feel the order table should contain the shipping_address_id
and the shipping address should contain the order_id
, right? This just made everything more confusing.
Please help me about this.
This happens because your current design means it's possible for multiple user_order
rows to reference the same single shipping_address
row.
You need to change the design so that it's impossible for multiple user_order
rows to reference the same single shipping_address
row.
There are at least two different possible solutions:
UNIQUE
constraint on user_order.shipping_address_id
user_order.shipping_address_id
column.shipping_address.id
to shipping_address.order_id
, so that it's a foreign-key of user_order.id
shipping_address.order_id
the new primary key of shipping_address
.Note that both of these options are a denormalization as it prevents the sharing of shipping addresses between different orders (e.g. if the same customer makes the same repeat order a lot) though this can be intentional - so that if a user's future address changes it won't unintentionally retroactively update old order shipping records.
A few other tips:
int
rather than bigint
for your identities - I doubt you'll have over 2 billion rows in each table.varchar(255)
for all text columns - use it to enforce reasonable constraints on data length, for example state
doesn't need to be longer than 2 characters if you're storing abbreviations, ditto zipcode
which can be varchar(10)
if you're using ZIP+4.payment
table) - This is a violation of PCI Rules, a massive liability and probably illegal negligence in your jurisdiction. Your payment processor will provide you with a substitute opaque token value (or something similar) as a means of identifying charge-cards and applying future charges to stored payment details - the most you can reasonably store is the last 4 digits. Whether or not your encrypt the data is largely irrelevant.