Insert new record when updating information? - mysql

I am developing online shopping cart system, I have items and item_options tables.
Each Item can have 1 or more options, see below.
items table
item_id (PK)
item_name
item_description
Note: item prices are in the item_options tables
item_options table
option_id (PK)
item_id (FK)
option_name
option_price
When the customer placed an order, the data will be added into the order and order_items table.
orders table
orders_id (PK)
customer_id (FK)
address_address_id (FK)
date_purchased
orders_status
orders_date_finished
order_items table
orders_items_id (PK)
orders_id (FK)
item_id (FK)
item_option_id (FK)
There is a problem, if the staffs change the price, item name or delete a item.. the customer invoices will be affected because the FK from the order_items will no longer be existed in the items table. What is the solution to this?
How about this solution: add active field in the items and item_options tables. When the staffs want to change the price or name of a item - just turn the current active record to 0 (items.active) and then insert a new record with the new information and active become 1. The old orders still point the correct id of the entry that is not active. Is this good way doing it?
When the new information has been inserted in the items table, does that mean I have to update/change the new PK ID in the item_id.item_options table?

In something like this, I am definitely against the use of hard deletes. Every update or delete should be adding a new row into the item_options table and then marking the previous one as inactive (that way there is no chance that a user can select one of the previous values).
Each new item inserted should consist of two steps:
Add the item to the items table
Using the item_id from the items table, add the item into the item_options table

The typical solution to this that I've seen is to store the snapshot of the data that you want a history of in a separate table. That way you can store only the data you want a snapshot of at the time of the invoice, instead of all data in a particular table.
It will also help to store history data away from live data when it comes to simplifying reporting and queries in the code.. generally these two things don't need to be accessed at the same time, so you avoid the more complex queries (and heavier load on a single table) just to access one or the other.

If you are going to do things the way you describe, you are going to have to add a new rows to the item_options table to handle the new items.

Related

MySQL table for saving a quantity to a 1:M relationship

I have a tables called invoice, item and invoice_item. The invoice item tables has invoice_id and item_id columns to store a 1:M type relationship, where an invoice can have many items.
Now I want to somehow store information for item quantity. Would it be suitable to create an invoice_item_quantity table, that store invoice_id, item_id and invoice_item_quantity values, respectively? Or would there be a more optimal solution?
I could be over-engineering this, but adding something like a item_quantity column to the invoice table won't work cause you can have many different types of items, so there would be no context there.
I basically need a way to store a model like this:
Invoice
Item 1 x 5
Item 2 x 2
Item 3 x 15
How can I optimally store the quantities in the model above?
I may be misunderstanding, but it sounds like you have a many-to-many relationship between the invoice and item tables, and that you are using a junction table to support this with the invoice_item table (this junction has a one-to-many relationship with both invoice and item).
If you are looking for a typical, normalized database design, then storing the quantity on the invoice_item table is good. Another good idea would be to make the invoice ID and the item ID a compound primary key on your junction table.

Database design issue in project?

I am designing a database for my app. In which I want to do mapping between multiple tables. Now situation is like There is one user table. User can have generate multiple orders. So I was thinking if I can put json obejct of order_id in a column in order table. Or I can create a user_id column in order table & repeat user_id for same user. So which is a better way of doing it?
PS: What is the standard way of doing it?
You should just have user_id in your order table, then make queries like
select * from orders where user_id = *some_user_id*
A user can place multiple orders which in turn can have multiple line items. Each line item can have n quantity of a specific product. So when product comes in picture, then it becomes many to many relationship between user and product because a user can place order for many products and a product can be ordered by many users. So my suggestion is -
Create a User table with UserID
Create a PurchaseOrder table with OrderID, UserID and LineItemID
Create a LineItem table with OrderID, ProductID and LineItemID
Create a SKU table with ProductID
A user can place multiple orders.
Based on this you should maintain three different tables as given below:
User (user_id,...)
Order (order_id,...)
UserOrder (user_id,order_id,...)
Only the primary keys in the above tables are focused
Storing comma separated list or json object will worsen the design. And this is strongly discouraged.
EDIT:
As #NevilleK suggested, the above design is typically used for many-to-many relationships. For one-to-many relationship you can create a foreign key constraint in orders table where user_id should refer to the user_id in the User table.
But still you can adopt the above design for one-to-many relationship since many-to-many qualifies for one-to-many too.
The best way is to have different table for your
User table - which hosts the user information
Transaction table - which will have order_id against each user_id.
Transaction table will carry all the transaction details with user_id. If you create a JSON object, how will you map the USER to the transaction. So at the time of retrieving the json information you will have to map it to the user table anyway. I suggest you the use the above said method, which will help you maintain and scale your application much easily.

MS Access Creating a New Order And Orderline

I have a Customer table, an Order table, an Orderline table and a Product table. All of them have an Autonumber field as their primary key, and Orderline has a foreign key reference to Order ID on Order table:
ORDER
-----
Order ID - Autonumber
Customer ID - Number
...
ORDERLINE
---------
OrderLine ID - Autonumber
Order ID - FK to Order
Product ID - FK to Product
Quantity
PRODUCT
-------
Product ID - Autonumber
Product details...
I have a form where I can choose a customer, and then a list of records from the Orderline table, and a query which I reference from this sub-form which lists the Order ID, Orderline ID, Product ID, Product details...
I have 2 problems.
All the orders appear, and I only want the ones associated with this order, (which should be none when the form first loads).
When I enter a Product ID that I want to add to a new order, I am expecting a new Order ID to appear, (Autoincremented) AND a new Orderline ID, (Autoincremented) and the details of the product that I have selected, corresponding to theProduct ID` I have entered, but instead I get this error message:
The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again
The thing is, the tables should create me unique keys when I try to create the new record, and when I go into each table directly and enter a new record, the autonumber does work and does create a unique key - it is just when it is trying to create both the Order ID and the Orderline ID at the same time that it seems to be failing.
I should say, I have spent days on this, searched countless search engines, watched whole series of YouTube videos on creating Order forms but to no avail. Anyone who understands Access I am sure would be able to help me, as I would be able to help anyone in a similar circumstance in a matter of minutes if this was a problem in SQL.
When you create a sub-form you have to specify the relationship between the parent and sub-form. the same relationship you have created for your tables. Then only Access will filter the records for you.
Regarding your question. You should create a new [order] record in [order] table where you will be entering/selecting [customer_id, staff_id, order details ect]
one order can have more than one items so your [order_items] table (i assume orderline is the term you use for this table) exists of
order_id
product_id (order_id, product_id composite key)
quantity
price
etc..
Now when you want to start taking order you need to create a new form that is bound to tbl_order. In the frm_order you will have a sub-from which is bound to tbl_oder_items (in your case orderline)
The frm_order and frm_oder_items should be have a relationship. usually when you drag the table to create the subform ACCESS will ask to set the relationship. if you create the subform manually:
Select the sub-form
go to property sheet
select the link master field : order_id
select the link child field : order_id
Now when you open the frm_order it will show all the records (in other words all the products the order has in its list) from the tbl_order_items table.
Your tbl_order_item /orderline table also referencing to the product table via the product_id field.
Insert a combobox in the frm_order_items and bound it to the product_id. The combobox's rowsource would be
select product_id, product_name from tbl_product
This error message will occur:
'The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again'
when you try to add a product twice for the same order. instead you should increase the quantity for the product.
Try this and let us know how it went.

Store a unique reference to a Mysql Table

I am creating a site that is sort of ecommerce-ish. I want to give my users a perfect search ability using specific attributes that differ from product to product. I plan to create 1 products table storing the basic information that is shared among products i.e Name, Description, Price and a few others. Then I plan to create several "details" table say categories_computers with columns Processor, HDD, RAM, etc and another table say table_shoes with columns MATERIAL, SIZE, GENDER, etc.
I am new to Mysql but not to the concept of Databases. I don't think I will have a problem storing this data to each table. My issue comes about from reads. It won't be hard to query a product id but I think it would be extremely wasteful to query all details tables to get the details of the product since 1 product can only have 1 details.
So my question is how can I store a reference to a table in a column so that a product has say ID, Name, Description, Price, Details_Table_ID or something similar to save on queries. Do tables have unique ids in Mysql? Or how does the Stackoverflow community suggest I go about this? Thanks.
EDIT
Silly me, I have just remembered that every table name is uniques so I can just use that, so my question changes to how I can write a query that contains one cell in a table A to be used as a reference to a Table name.
Don't use separate details tables for each category, use a generic details table that can store any attribute. Its columns would be:
Product_ID INT (FK to Products)
Attribute VARCHAR
Value VARCHAR
The unique key of this table would be (Product_ID, Attribute).
So if Product_ID = 1 is a computer, you would have rows like:
1 Processor Xeon
1 RAM 4GB
1 HDD 1TB
And if Product_ID = 2 is shoes:
2 Material Leather
2 Size 6
2 Gender F
If you're worried about the space used for all those attribute strings, you can add a level of indirection to reduce it. Create another table Attributes that contains all the attribute names. Then use AttributeID in the Details table. This will slow down some queries because you'll need to do an additional join, but could save lots of space
Think about just having a single ProductDetails table like this:
ProductDetailID (PK)
ProductID (foreign key to your Products table)
DetailType
DetailValue
this way you do not have to create new columns every time you add a new product detail type. and you'll have many ProductDetail rows for each productid, which is fine and will query ok. Just be sure to put an index on ProductDetails.ProductID !
Since this is an application so you must be generating the queries. So lets generate it in 2 steps. I assume you can add a column product_type_id in your Product table that will tell you which child table to user. Next create another table Product_type which contains columns product_type_id and query. This query can be used as the base query for creating the final query e.g.
Product_type_id | Query
1 | SELECT COMPUTERS.* FROM COMPUTERS JOIN PRODUCT ON COMPUTERS.PRODUCT_ID = PRODUCT.PRODUCT_ID
2 | SELECT SHOES.* FROM SHOES JOIN PRODUCT ON COMPUTERS.PRODUCT_ID = PRODUCT.PRODUCT_ID
Based on the product_id entered by the user lookup this table to build the base query. Next append your where clause to the query returned.

User inventory database design?

I'm making a game in PHP with MySQL and I was wondering what is the best way for me to store the items the users have purchased so it is linked with their account.
I plan to have a database with the items information in and the only ways I could think of doing it was:
Having a table for the users items in a serialised array of sort
Having masses of columns with a set amount of inventory space
Table with user_id and item_id and add a row every time they purchase an item, selecting the user_id relevant to the user to display their items
Which is best?
I think that you know at the beginning which items a user can buy, so in my opinion you should have three tables
USERS table, in which you store user data (PRIMARY KEY is user_id)
ITEMS table, in which you store items with their cost and data (PRIMARY KEY is item_id)
USERITEMS table, in which you store every item bought by users. It should have two columns: user_id and item_id and you add a row every time a user buy an item.
This design lets you easily manage bought items and show every user its inventory.
More: you avoid wasting space in database duplicating unuseful informations
As per your question, the No.3 is suitable.I prefer #Marco suggestion.