I think your main challenge is the requirement that the Order
is in between your User
and Cart_Item
.
I am assuming you are planning on storing items put in the shopping cart in Cart_Item
(items planned to be purchased but not currently purchased. Also there is only 1 list of items pending purchase per user). And then items actually purchased by the user (coming from he shopping cart) will land in Order
. In my opinion, there should not be any kind of link between the "order" and the "shopping cart". If there was, you would need to store some kind of Cart_ItemId
on the Order
table, not an orderId
on Cart_Item
. If you were to keep a Cart_ItemId
, you would then have to have some kind of shopping cart history, which to me, seems redundant since that data would be saved in your "order history" though Order
. You may have another purpose that I am not thinking of so let me know if I am missing something.
Assuming my understanding of what you are looking for is correct. I believe this below schema is much closer to giving you what you are looking for, and getting you around this Foreign Key
issue. (I apologize, your relationship diagram was so much nicer than mine. Trying to make it work in Visio instead):
Transferring data from your Cart to Your Order could look something like this:
CREATE PROCEDURE [FinalizeOrder] (@UserID INT, @OrderDetails VarChar(500))
AS
BEGIN
INSERT INTO Order_Item
(
userID,
orderProductId,
quantity,
price,
[date],
details
)
SELECT
CI.userID, --userID,
CI.cartItemProductID, --orderProductId,
CI.quantity, --quantity,
P.price, --price,
GETDATE(), --[date],
@OrderDetails --details
FROM Cart_Item CI
INNER JOIN Product P
ON CI.cartItemProductID = P.ProductId
WHERE CI.userID = @UserID
DELETE FROM Cart_Item
WHERE CI.userID = @UserID
END
Now if it was me, I would create Order
and OrderItems
tables. That way you don't duplicate data like the User, or address information on each item. I know you want to limit tables that are created, but I think that will help you a lot. If that is a route you end up going, than you will have a schema a little like this:
For a quick example. Lets pretend I am a user (UserID 13 because that is my favorite number). I fill out a cart with the 5 items. The records from the Cart_Item
table looks like:
+------------+--------+-------------------+----------+
| CartItemId | UserID | CartItemProductID | quantity |
+------------+--------+-------------------+----------+
| 1 | 13 | 123 | 1 |
| 2 | 13 | 456 | 2 |
| 3 | 13 | 789 | 5 |
| 4 | 13 | 123456 | 77 |
| 5 | 13 | 56 | 45 |
+------------+--------+-------------------+----------+
When I hit the last "submit" in the check out process we would then write 1 record to Order
and 5 rows to Order_Item
. Those rows would look something like:
[ORDER]
+----------+--------+----------+--------------------------------------------------------+
| OrderId | UserId | Date | Details |
+----------+--------+----------+--------------------------------------------------------+
| 98564745 | 13 | 4/6/2020 | Order Placed by Kirk Saunders on 4/6/2020 for 5 items. |
+----------+--------+----------+--------------------------------------------------------+
[ORDER_ITEM]
+----------+--------------------+----------+-------+
| OrderID | OrderItemProductID | Quantity | Price |
+----------+--------------------+----------+-------+
| 98564745 | 123 | 1 | 1 |
| 98564745 | 456 | 2 | 1.5 |
| 98564745 | 789 | 5 | 7.98 |
| 98564745 | 123456 | 77 | 85.99 |
| 98564745 | 56 | 45 | 1065 |
+----------+--------------------+----------+-------+
A Stored Procedure to handle this might look like:
CREATE PROCEDURE [FinalizeOrder] (@UserID INT, @OrderDetails VarChar(500))
AS
BEGIN
DECLARE @OrderId INT
INSERT INTO [Order]
(
userID,
[date],
details
)
VALUES
(
@userID, --userID,
GETDATE(), --[date],
@OrderDetails --details
)
SET @OrderId = scope_identity()
INSERT INTO Order_Item
(
OrderId,
OrderItemProductID,
Quantity,
Price
)
@OrderId, --OrderId,
CI.cartItemProductID, --OrderItemProductID,
CI.Quantity, --Quantity,
P.Price --Price
FROM Cart_Item CI
INNER JOIN Product P
ON CI.cartItemProductID = P.ProductId
WHERE CI.userID = @UserID
DELETE FROM Cart_Item
WHERE CI.userID = @UserID
END
Hopefully this helps. Let me know if I need to explain something better or if this doesn't answer your question.