3

I currently have a table with a person's username, password, email, and items (by items I mean like items that you can collect in a game also called an "inventory"). However, how can I add multiple items in the items column? For example if I want to add item A, B, and C in here:

enter image description here

7
  • 2
    You don't want to do that. That's poor database design. Commented Feb 2, 2013 at 20:07
  • You Can Use JSON for code Item And seve them On One Item Commented Feb 2, 2013 at 20:08
  • 1
    You can store items as JSON, and then parse the JSON when loading, etc. I would not do this if you want to query by the items, however. Commented Feb 2, 2013 at 20:08
  • @JohnConde Ahh, okay. What would be a better way to approach something like this? Commented Feb 2, 2013 at 20:08
  • See my answer for sample SQL Commented Feb 2, 2013 at 20:09

3 Answers 3

13

You should use 2 tables to store this data.

users: username | password | email ------------------------- items: username | item 

You can then insert an unlimited number of items for a given username in the second table (each item is a new record).

You can then select all the items for one user like this:

SELECT item FROM items WHERE username = ? 

You can also combine the 2 tables in a number of ways.

/* this one selects all users who have a specific item */ SELECT u.* FROM users u JOIN items i ON u.username = i.username WHERE i.item = ? 

How do you wish to use the data?

You should also start to use ID values (numbers) so that the you don't have to waste space repeating text based content such as the username.


I think this might be a really good way, however can you show me what you mean by each item is a new record? I'm still a bit confused.

You could insert the values like this:

insert into items values ('jonathan', 'hat'); insert into items values ('jonathan', 'drink'); insert into items values ('jonathan', 'mouse'); insert into items values ('user1981730', 'hat'); insert into items values ('user1981730', 'mouse'); 

Which would result in this:

Then you could query for all users who have drink as an item:

SELECT u.* FROM users u JOIN items i ON u.username = i.username WHERE i.item = 'drink' 

Then to fetch a list of all items obtained by user1981730:

SELECT item FROM items WHERE username = 'user1981730' 

Once you are happy with this we can talk about adding ID columns.


what do you mean by ID columns?

Notice that in the above example the items table has a lot of duplicate information. The username jonathan is repeated 3 times, the item hat is repeated twice. This would be much worse with a real database.

We can save space and generally increase performance by using an integer ID to represent each unique value. Each user would have an ID and so would each unique item.

Let's start with just the users. We must add the new column to the users table.

We make it a PRIMARY KEY which will ensure that all values are unique so that no 2 users can have the same ID. We can also use the AUTO_INCREMENT to have the value automatically increase with each new record.

We would then change our items table so that it made use of the new column instead of username.

Notice how we still have the same information that we did before. User with ID number 1 has a drink, hat and a mouse and the user with ID number 2 has the hat and mouse.

We can still do the same queries as before (with some small changes).

/* this selects all the items for a known user_id */ SELECT item FROM items WHERE user_id = ? /* this selects all the items for a user when we only know the username */ SELECT i.item FROM items i JOIN users u ON u.user_id = i.item_id WHERE u.username = ? /* this one selects all users who have a specific item */ SELECT u.* FROM users u JOIN items i ON u.user_id = i.user_id WHERE i.item = ? 

So far we have only modified the tables to avoid duplicating the username. If we wanted to also avoid duplicating item names we can add an additional table. This starts to get tricky so I won't go into too much detail (for now) but the table structure would be as follows:

users: username | password | email ------------------------------- items: item_id | name ------------------------------- users_items: user_id | item_id 

The users table is as before. The items table has a new role and it stores all the unique items. The users_items table now links the other 2 tables.


I will end the SO answer here. If you have any further question you can email me with the address listed above (the one used in the example table).

Sign up to request clarification or add additional context in comments.

3 Comments

I think this might be a really good way, however can you show me what you mean by each item is a new record? I'm still a bit confused.
Wow! Those edits were great, thank you SO much for you help! :) I am definitely happy with this, hmm, what do you mean by ID columns?
This is by far, the BEST answer I have EVER received on StackOverFlow. This just blew my mind and I understand everything so much better now. Thank you SO much! :)
1

Make a row for each item in a separate table.

INSERT INTO items (userid, item) VALUES (1, 'item number 1'), (1, 'item number 2'), (1, 'item number 3'); 

Don't put all items in one row in your user table. JSON, comma separated values, and other techniques may sound tempting but they aren't real solutions. Your SQL and logic will be much simpler and cleaner if you have one row per item in a table dedicated to keeping track of them.

6 Comments

if we Do This Our DB Doesn't Be Huge IF We Have More Than 20 Filed , That Some Filed is for Big Text ?
Databases can handle huge amounts of information without any issues. They're designed specifically for that.
Lets say if there were a few hundred users and if each of them have about 20-30 items, wouldn't that be a bit too much?
That wouldn't be a problem at all. You could have millions of users and with hundreds of items and that wouldn't be a problem either. This is the kind of stuff databases were designed for. Take advantage of it. :)
Wow, I'm glad to hear that! :) Also, is this answer and the answer by diolemo on this question the same thing?
|
0

You have several options. Either (if the use case is simple enough), just encode multiple values, e.g., by separating with commas.

However, the clean approach is to use another table, where you create one entry per item and have a foreign key which points to your first table.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.