To allow users manage their addresses, you'll need to store info for whether the address has been used in purchase (by checking the purchases
table or a separate flag in the addresses
table). The key part of the solution here is this flag or check in the database indicating that an address has been used in a purchase, as mentioned by @sqlvogel.
This one piece of info will allow the following scenarios:
- Letting the user enter a new address - will not have an existing reference in the purchases history, so can also be edited before purchase.
- Letting the user pick an existing address, which may or may not have been used in a previous purchase.
- Letting the user change the address for a purchase, either by editing a new and unused address or picking one of the previously used addresses.
- If a user edits an existing and used address, save it as a new address instead of editing the original (and a good idea to let them know/see that a new address has been added).
You can provide a pseudo-deletion feature by adding a flag to an address indicating that it's a historical record (which you should also allow your users to know).
Shipping vs Billing address id: You may already have done this but these two need to be separate columns in the purchase table. So history is kept accurately with the controls above.