MySQL Lookup table and id/keys - sql

Hoping someone can shed some light on this: Do lookup tables need their own ID?
For example, say I have:
Table users: user_id, username
Table categories: category_id, category_name
Table users_categories: user_id, category_id
Would each row in "users_categories" need an additional ID field? What would the primary key of said table be? Thanks.

You have a choice. The primary key can be either:
A new, otherwise meaningless INTEGER column.
A key made up of both user_id and category_id.
I prefer the first solution but I think you'll find a majority of programmers here prefer the second.

You could create a composite key that uses the both keys
Normally if there is no suitable key to be found in a table you want to create a either a composite key, made up of 2 or more fields,
ex:
Code below found here
CREATE TABLE topic_replies (
topic_id int unsigned not null,
id int unsigned not null auto_increment,
user_id int unsigned not null,
message text not null,
PRIMARY KEY(topic_id, id));
therefor in your case you could add code that does the following:
ALTER TABLE users_categories ADD PRIMARY KEY (user_id, category_id);
therefor once you want to reference a certain field all you would need is to pass the two PKs from your other table, however to link them they need to each be coded as a foreign key.
ALTER TABLE users_categories ADD CONSTRAINT fk_1 FOREIGN KEY (category_id) REFERENCES categories (category_id);
but if you want to create a new primary key in your users_categories table that is an option. Just know that its not always neccessary.

If your users_categories table has a unique primary key over (user_id, category_id), then - no, not necessarily.
Only if you
want to refer to single rows of that table from someplace else easily
have more than one equal user_id, category_id combination
you could benefit from a separate ID field.

Every table needs a primary key and unique ID in SQL no matter what. Just make it users_categories_id, you technically never have to use it but it has to be there.

Related

SQL - How to save data with a key value

My question: is there a way to save data into a SQL database with a key value? I have an example below.
As you see in the example table below, in column Friends I have ""Uno", John". "Uno" would be the key value that is associated with "John".
I would be able to get the data from "Uno" like this:
SELECT *
FROM Table_Name
WHERE KEY VALUE = "Uno"
Is saving data like this possible? If not, I would love some suggestions!
Thank you!
Saving keys is not only possible, but it's also one of the fundamental abilities of relational databases. You don't want to store friends' names though, just store keys of them and make an SQL query to get names from keys.
This is a pseudocode you might use, but it might not compile for every DBMS
CREATE TABLE people (
id INT NOT NULL PRIMARY KEY,
name CHAR(30)
);
CREATE TABLE friends (
person_id INT NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES people(id),
friend_id INT NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES people(id)
);

Composite key + autoincrement field

I have a table Tags which has 2 columns:
name VARCHAR(50)
group_id INT
The combination on both cannot be repeated so I use a composite key to make sure that the combination of name and group_id cannot be used 2 times.
But since the name is a varchar column, it is not a very good option for querying the database, so if I use an id column which is not a primary key but is an autoincrement, I can search for only one column in the database will be ok?
The table will be like this:
name VARCHAR(50) PRIMARY KEY,
group_id INT PRIMARY KEY
id autoincrement NOT NULL
I never seen this before and it looks like a solution, but I really need other point of view before applying this solution.
I have to import the tags from a file and those tags have a many many relation with another table that I'm also importing from the file, just to illustrate the file structure is like this:
enterprises |TagGroup1 |TagGroup2 |...TagGroupN
Google |t1.1,t1.2 |t2.1,t2.2 |tN.1,tN.2
canonical |t1.1.1 |t2.1,t2.2 |tN.1,tN.2
given this file I'll explain that a tag belongs to a group and an enterprise has tags so when I import the file I import the group and then create the tags in bulk, them import enterprises but when I need to import the relation between tags and enterprises if I have need the tag numeric id that will force me to insert the tags one by one which is not a good idea at all, but if I had the name and group ID as key I not longer need to wait for the tag's ID...
sorry this is to long and I'm trying to explain my problem but I don't know if I succeeded in making this simple to understand
[…] so I use a composite key to make sure that the combination of name and group_id cannot be used 2 times.
You are describing a need for a constraint; that doesn't need to be a key at all. When defining a table you can specify a constraint that multiple fields need to be unique together:
CREATE TABLE tag (
name varchar(50),
group_id int,
UNIQUE (name, group_id) );
That way you get the RDBMS enforcing those columns have a unique pair of values on each record, without implying that they are a key for retrieval.
So then you are free to nominate whatever primary key you like. Because you want the id field to be primary key, go for it:
CREATE TABLE tag (
name varchar(50),
group_id int,
id serial NOT NULL,
UNIQUE (name, group_id),
PRIMARY KEY (id) );

SQL How to not insert duplicated values

I'm trying to create a procedure that inserts data into a table of registers but i don't want to repeat the second parameter, this is the table
CREATE TABLE Inscription
(
idClass INT references tb_class,
idStudent INT references tb_student,
)
The idea is that a student (idStudent) can register in various classes but not in the same class (idClass), I tried to add a unique constraint in the idStudent column but that only allows a student to register in one single class.
I always suggest that all tables have a numeric primary key. In addition, your foreign key references are not correct. And what you want to do is add a unique constraint.
The exact syntax depends on the database. The following is for SQL Server:
CREATE TABLE Inscriptions (
idInscription int identity(1, 1) primary key
idClass int references tb_classes(idClass),
idStudent int references tb_students(idStudnt)
unique (idClass, idStudent)
);
Notice that I name the tables as the plural of the entity, but the id using the singular.
The Inscriptions table probably wants other columns as well, such as the date/time of the inscription, the method, and other related information.
You are looking to create a constraint on your table that includes both columns idClass and idStudent.
Once that constraint is created, an attempt to insert duplicate class/student will result in an error being raised.
As your table does not seem to include a primary key, you would better make that constraint your primary key.
NB : you did not tell which RDBMS you are using hence cannot give you the exact syntax to use...
Your unique key needs to encompass both idClass and idStudent, so any particular combination cannot repeat itself.

Correct way to create a table that references variables from another table

I have these relationships:
User(uid:integer,uname:varchar), key is uid
Recipe(rid:integer,content:text), key is rid
Rating(rid:integer, uid:integer, rating:integer) , key is (uid,rid).
I built the table in the following way:
CREATE TABLE User(
uid INTEGER PRIMARY KEY ,
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY,
content VARCHAR NOT NULL
);
Now for the Rating table: I want it to be impossible to insert a uid\rid that does not exist in User\Recipe.
My question is: which of the following is the correct way to do it? Or please suggest the correct way if none of them are correct. Moreover, I would really appreciate if someone could explain to me what is the difference between the two.
First:
CREATE TABLE Rating(
rid INTEGER,
uid INTEGER,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid),
FOREIGN KEY (rid) REFERENCES Recipes,
FOREIGN KEY (uid) REFERENCES User
);
Second:
CREATE TABLE Rating(
rid INTEGER REFERENCES Recipes,
uid INTEGER REFERENCES User,
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
EDIT:
I think User is problematic as a name for a table so ignore the name.
Technically both versions are the same in Postgres. The docs for CREATE TABLE say so quite clearly:
There are two ways to define constraints: table constraints and column constraints. A column constraint is defined as part of a column definition. A table constraint definition is not tied to a particular column, and it can encompass more than one column. Every column constraint can also be written as a table constraint; a column constraint is only a notational convenience for use when the constraint only affects one column.
So when you have to reference a compound key a table constraint is the only way to go.
But for every other case I prefer the shortest and most concise form where I don't need to give names to stuff I'm not really interested in. So my version would be like this:
CREATE TABLE usr(
uid SERIAL PRIMARY KEY ,
uname TEXT NOT NULL
);
CREATE TABLE recipes(
rid SERIAL PRIMARY KEY,
content TEXT NOT NULL
);
CREATE TABLE rating(
rid INTEGER REFERENCES recipes,
uid INTEGER REFERENCES usr,
rating INTEGER NOT NULL CHECK (rating between 0 and 5),
PRIMARY KEY(rid,uid)
);
This is a SQL Server based solution, but the concept applies to most any RDBMS.
Like so:
CREATE TABLE Rating (
rid int NOT NULL,
uid int NOT NULL,
CONSTRAINT PK_Rating PRIMARY KEY (rid, uid)
);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_Recipies FOREIGN KEY(rid)
REFERENCES Recipies (rid);
ALTER TABLE Rating ADD CONSTRAINT FK_Rating_User FOREIGN KEY(uid)
REFERENCES User (uid);
This ensures that the values inside of Rating are only valid values inside of both the Users table and the Recipes table. Please note, in the Rating table I didn't include the other fields you had, just add those.
Assume in the users table you have 3 users: Joe, Bob and Bill respective ID's 1,2,3. And in the recipes table you had cookies, chicken pot pie, and pumpkin pie respective ID's are 1,2,3. Then inserting into Rating table will only allow for these values, the minute you enter 4 for a RID or a UID SQL throws an error and does not commit the transaction.
Try it yourself, its a good learning experience.
In Postgresql a correct way to implement these tables are:
CREATE SEQUENCE uid_seq;
CREATE SEQUENCE rid_seq;
CREATE TABLE User(
uid INTEGER PRIMARY KEY DEFAULT nextval('uid_seq'),
uname VARCHAR NOT NULL
);
CREATE TABLE Recipes(
rid INTEGER PRIMARY KEY DEFAULT nextval('rid_seq'),
content VARCHAR NOT NULL
);
CREATE TABLE Rating(
rid INTEGER NOT NULL REFERENCES Recipes(rid),
uid INTEGER NOT NULL REFERENCES User(uid),
rating INTEGER CHECK (0<=rating and rating<=5) NOT NULL,
PRIMARY KEY(rid,uid)
);
There is no real difference between the two options that you have written.
A simple (i.e. single-column) foreign key may be declared in-line with the column declaration or not. It's merely a question of style. A third way should be to omit foreign key declarations from the CREATE TABLE entirely and later add them using ALTER TABLE statements; done in a transaction (presumable along with all the other tables, constraints, etc) the table would never exist without its required constraints. Choose whichever you think is easiest fora human coder to read and understand i.e. is easiest to maintain.
EDIT: I overlooked the REFERENCES clause in the second version when I wrote my original answer. The two versions are identical in terms of referential integrity, there are just two ways of syntax to do this.

Does MySQL allow two primary keys on one table?

CREATE TABLE Orders
-> (
-> ID SMALLINT UNSIGNED NOT NULL,
-> ModelID SMALLINT UNSIGNED NOT NULL,
-> Descrip VARCHAR(40),
-> PRIMARY KEY (ID, ModelID)
-> );
Basically, this appears to me to be creating two primary key on one table. Is that correct?
I thought that we could create a number of unique keys in one table, but only one primary key.
How is it that my system is allowing the creation of multiple primary keys?
Please advise: what are the rules governing this?
Your system is not allowing multiple primary keys - it is creating the key based on 2 columns (ID, ModelID)
Think of it like it suggest, a 'KEY'. So the key would be all of the columns specified. In your case you can have multiple rows with the same 'ID' and multiple rows with the same 'ModelID' but there shall never be two rows that have the same 'ID' AND 'ModelID'.
So in this case it is not saying that the column 'ID' must be unique nor is it saying that 'ModelID' must be unique, but only the combination.
You are making 1 primary key. But that key is a combination of 2 values.
Which is not a wrong thing to do. But in your case it does look wrong.
You seem to have a primary key named ID and a foreign key named ModelID. You should probable have an index on the ModelID, and a primary key constraint on the ID
You can have one primary key (thats why it is called the primary key)
You can have multiple UNIQUE keys if you like.