I am in an argument with a friend of mine on how to store a small array (<10) of references in SQL. Lets say there is a class player which can hold one item in it's inventory. Describing this as an SQL table would be fairly straight forward:
CREATE TABLE items(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(32),
weight FLOAT
);
CREATE TABLE players(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) not null,
item INT,
FOREIGN KEY(item) REFERENCES items(id)
);
The question is now: If the player could hold more than one item, but a small fixed amount of them, would it be better to store them in an additional table and then JOIN
over them, like this:
Additional Table
CREATE TABLE players(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) not null
);
CREATE TABLE inventory(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
item INT NOT NULL,
player INT NOT NULL,
FOREIGN KEY(item) REFERENCES items(id),
FOREIGN KEY(player) REFERENCES players(id)
);
Or would it be better to just add additional columns? If the amount of items was dynamic and unlimited, this would of course not be an option:
Multiple Columns
CREATE TABLE players(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) not null
item1 INT,
item2 INT,
item3 INT,
item4 INT,
FOREIGN KEY(item1) REFERENCES items(id)
FOREIGN KEY(item2) REFERENCES items(id)
FOREIGN KEY(item3) REFERENCES items(id)
FOREIGN KEY(item4) REFERENCES items(id)
);
This would have the advantage of not having to join over a table that would grow very big very fast but might fragment your table very fast if not any player is carrying all four items all the time.
- Which way should be preferred?
- Is the second way using multiple columns violating the first normal form?
- What are the advantages and disadvantages to both ways?
- What will deliver the best performance?