Primary keys in sql - mysql

I have here some problems undersanding how this works.
So I have 2 tables Students and Enrolled like this:
CREATE TABLE Students
(sid CHAR(20),
name CHAR(50),
email CHAR(30),
age INTEGER,
gr INTEGER)
CREATE TABLE Enrolled
(sid CHAR(20),
cid CHAR(20),
grade CHAR(2),
PRIMARY KEY (sid,cid))
So I don't understand this particulary row PRIMARY KEY (sid,cid)
Can someone explain to me how it works? I have to specify that I have another table Courses from where the cid.
Is is equivalent saying like this:
CREATE TABLE Enrolled
(sid CHAR(20) foreign key references Students(sid),
cid CHAR(20) foreign key references Courses(cid)
)

A PRIMARY KEY is used to identify a table. A field or column that is defined as PRIMARY KEY will contains different values on each row in that table, and is mandatory to have a value (so, PRIMARY KEY is equivalent to UNIQUE and NOT NULL).
PRIMARY KEY can be a single field, or multiple fields, but it always satisfy that "each row will have a different PRIMARY KEY".
If you declare as PRIMARY KEY a combination of 2 columns, you will be able to have this for example:
CREATE TABLE Enrolled
(sid CHAR(20),
cid CHAR(20),
grade CHAR(2),
PRIMARY KEY (sid,cid)) --PRIMARY KEY with combination of 2 columns
sid | cid | grade
1 1 XX
1 2 XX
2 1 XX
2 2 XX
2 3 XX
In this example, you can see that the column sid or the column cid has repeated values individually, but there isn't a combination of (sid, cid) that was repeated.
Like a PRIMARY KEY is used to identify a row in a table, when we want to relate two tables we can define a FOREIGN KEY in one table to link this one with the other table.
Your case is that the ENROLLED table is identified by a composite PRIMARY KEY to represent a many-to-many relationship. That is the way to say that:
A student can be enrolled in many courses.
A course can have enrolled many students.
Note*: Is a best practice to define the PRIMARY KEYS as numeric values, such integer, bigint, etc. because it is better to improve the indexes performance (all PRIMARY KEYS have defined inherently an INDEX, and they are faster working with "numeric" values than working with "string" values).

PRIMARY KEY (sid,cid) means composite primary key.. the combination of these field should be unique.

PRIMARY KEY means both UNIQUE and NOT NULL.
If you want sid and cid to also be FOREIGN KEY you have to specify that separately.
Having two fields for a primary key is often used for tables that are the physical representation of a many-to-many relation. In your database design diagram you would have STUDENT and COURSE as entities and ENROLLMENT as a many-to-many relationship between them.
In the physical database diagram many-to-many relationships are modelled as tables, often with a composite PRIMARY KEY and with FOREIGN KEY constraints to the entity tables.

Related

Primary Key/Foreign Key for a table with two junction tables

Lets say I have table A with two junction tables B and C, how would I go about creating primary keys for table A? I have two of these types of table in a diagram I drew, the circle keys are foreign keys btw.
Image with junction tables
Your games table needs only one primary key: this identifies each specific game. In the junction tables, the primary keys are composed of the game primary key and the directors (or types) primary key.
Taken from the reference in the tutorial MySQL Primary Key:
CREATE TABLE roles(
role_id INT AUTO_INCREMENT,
role_name VARCHAR(50),
PRIMARY KEY(role_id)
);
It is difficult to provide information about your specific question because there is too little details in it.
From your comment "if a table has two junction tables attached to it, would it need to have two primary keys?". No.
A primary key is actually a logical concept (a design mechanism) used to define a logical model. A primary key is a set of attributes (columns) that together uniquely identify each end every Tuple (row) in a relation (table). One of the rules of a primary key is that there is only one per relation.
The logical model is used, as mentioned, as the design to create the physical model, relations become tables, attributes become columns, Primary keys may become unique indexes. Foreign Keys may become indexes in the related table and so on.
Many RDBMS's allow the specification of a PRIMARY KEY in a physical table definition. Most also allow definition of FOREIGN KEYs on a physical table also. What they do with them may vary from one implementation to another. Many use the definition of a PRIMARY KEY to define a UNIQUE INDEX of some sort to enforce the "must uniquely identify" each and every record in the table.
So, No, your games_directors table does not need, nor can it have, two primary keys. if you did choose to specify a PRIMARY KEY, you would need to specify all the columns that uniquely identify records in the games_directors table - most likely PRIMARY KEY (game_id, director_id).
Similarly, the PRIMARY KEY for the games table would likely be PRIMARY KEY (game_id), for the directors would likely be PRIMARY KEY (director_id) and for game types it would likely be PRIMARY KEY (game_type_id).
You might use a foreign key from your games_directors table to ensure that when records are added to it that the corresponding director exists in the games table and the directors table. In this case, your games_directors table will have two foreign key relationships (one to games and another to directors). But only one PRIMARY KEY.
So you might end up with something like this:
create table games (
game_id integer,
PRIMARY KEY (game_id)
);
create table directors (
director_id integer,
PRIMARY KEY (director_id)
);
CREATE TABLE games_directors (
game_id INTEGER NOT NULL,
director_id INTEGER NOT NULL,
commission_paid DECIMAL(10,2),
PRIMARY KEY (game_id, director_id),
FOREIGN KEY (game_id) REFERENCES games(game_id),
FOREIGN KEY (director_id) REFERENCES directors(director_id)
);
NB: I didn't tested the above using PostgreSql. The syntax should work for most RDBMS's, but some may require tweaking slightly.
Indexes can be used to speed up access to individual records within table. For example, you might want to create an index on director name or director id (depending upon how you most frequenytly access that table). If you mostly access the director table with an equality condition like this : where director_name = 'fred' then an index on director_name might make sense.
Indexes become more useful as the number of records in the tables grows.
I hope this answers your question. :-)

When to use foreign key as a primary key at the same time?

I have get an intermediate table ArticleLanguage
idArticleLanguage
ArticleId
LanguageId
Name
Foreign keys are:
ArticleId
LanguageId
Should I use primary keys for:
ArticleId
LanguageId
Because these fields are primary keys in related tables?
Link / Junction Tables
Assuming the linked tables are defined as:
CREATE TABLE Article
(
ArticleId INT PRIMARY KEY
-- ... other columns
);
CREATE TABLE Language
(
LanguageId INT PRIMARY KEY
-- ... other columns
);
As per #JulioPĂ©rez Option 1, the link table could be created as:
CREATE TABLE ArticleLanguage
(
ArticleId INT NOT NULL,
LanguageId INT NOT NULL,
Name VARCHAR(50),
-- i.e. Composite Primary Key, consisting of the two foreign keys.
PRIMARY KEY(ArticleId, LanguageId),
FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);
i.e. with a composite primary key consisting of the two foreign keys used in the "link" relationship, and with no additional Surrogate Key (idArticleLanguage) at all.
Pros of this approach
Enforces uniqueness of the link, i.e. the same ArticleId and LanguageId cannot be linked more than once.
Saves an unnecessary additional surrogate key column on the link table.
Cons of this approach:
Any downstream tables which needs to reference this link table, would need to repeat both keys (ArticleId, LanguageId) as a composite foreign key, which would again consume space. Queries involving downstream tables which reference ArticleLanguage would also be able to join directly to Article and Language, potentially bypassing the link table (it is often easy to 'forget' that both keys are required in the join when using foreign composite keys).
SqlFiddle of option 1 here
The alternative (#JulioPĂ©rez Option 2), would be to to keep your additional surrogate PK on the reference table.
CREATE TABLE ArticleLanguage
(
-- New Surrogate PK
idArticleLanguage INT NOT NULL AUTO_INCREMENT,
ArticleId INT NOT NULL,
LanguageId INT,
Name VARCHAR(50),
PRIMARY KEY(idArticleLanguage),
-- Can still optionally enforce uniqueness of the link
UNIQUE(ArticleId, LanguageId),
FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);
Pros of this Approach
The Primary Key idArticleLanguage is narrower than the composite key, which will benefit any further downstream tables referencing table ArticleLanguage. It also requires downstream tables to join through the ArticleLanguage link table in order to get ArticleId and LanguageId, for further joins to the Language and Article tables.
The approach allows for an additional use case, viz that if it IS possible to add the same link to Language and Article more than once (e.g. two revisions or two reprints etc), then the UNIQUE key constraint can be removed
Cons of this Approach
If only one unique link per Article and Language is possible, then the additional surrogate key is redundant
SqlFiddle of option 2 here
If you're asking for an opinion, I would stick with option 1, unless you do require non-unique links in your ArticleLanguage table, or unless you have many further downstream tables which reference ArticleLanguage (this would be unusual, IMO).
Table per Type / per Class Inheritance
Unrelated to OP's post, but another common occurrence where a Foreign Key can be used as a Primary Key in the referencing table is when the Table per Type approach is taken when modelling an object oriented class hierarchy with multiple subclasses. Because of the 0/1 to 1 relationship between subclass and base class tables, the base class table's primary key can also be used as the primary key for the subclass tables, for instance:
CREATE TABLE Animal
(
AnimalId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- Common Animal fields here
);
CREATE TABLE Shark
(
AnimalId INT NOT NULL PRIMARY KEY,
-- Subclass specific columns
NumberFins INT,
FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);
CREATE TABLE Ewok
(
AnimalId INT NOT NULL PRIMARY KEY,
-- Subclass specific columns
Fleas BOOL,
FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);
More on TPT and other OO modelling in tables here
You have 2 ways:
1) Put "ArticleId + LanguageId" as your only primary key in "intermediate table" and you can name it as "idArticleLanguage". This is called a "composite" primary key because it is composed by 2 (in other case more than 2) fields, in this case 2 foreign keys (PK= FK + FK).
2) Create "idArticleLanguage" that has no relation to the other two "id" and set it as primary key.It can be a simple auto-increment integer.
Both alternatives are accepted. Your election will depend on the goal you want to achieve because what happens if you need to add in this intermediate table the same Article with the same language (Wilkommen German for example) because you have 2 different editions of the article? if you choose alternative 1 it will throw an error because you will have the same composite primary key for 2 rows then you must choose alternative 2 and create a completely different primary key for this table
In any other case (or purpose) you can choose alternative 1 and it will work perfectly
About the change of your question title:
When use foreign key as primary key in the same time?
I will explain it with this example:
You have 2 tables: "country" and "city". "country" have all the countries of the world, "city" have all the cities of the world. But you need to know every capital in the world. What you should do?
You must create an "intermediate table" (named as "capital") that will have every capital on the world. So, we know that country have it's primary key "idcountry" and city have it's primary key is "idcity" you need to bring both as foreign keys to the table "capital" because you will need data of "city" and "country" tables to fill "capital" table
Then "capital" will have it's own primary key "idcapital" that can be a composite one "idcity+idcountry" or it can be an auto-increment integer in both cases you must have "idcity" and "idcountry" as foreign keys on your "capital" table.

parent child table sql issue

i have 3 tables below which have many to many relation...In student table i have multiple foreign keys sec_id,ad_id but i dont know how to add foreign key as parent-child relation please help me out..
CREATE TABLE student(
s_id int AUTO_INCREMENT,
name varchar(30) NOT NULL,
PRIMARY KEY(s_id)
)
CREATE TABLE section(
sec_id int AUTO_INCREMENT,
name varchar(2) NOT NULL,
PRIMARY KEY(sec_id)
)
CREATE TABLE advisor(
ad_id int AUTO_INCREMENT,
name varchar(2) NOT NULL,
PRIMARY KEY(ad_id)
)
If a student can have at most one advisor, then it's a one-to-many relationship.
The normal pattern for implementing that relationship is to define a foreign key column in the child table, the table on the "many" side of the relationship. For example:
ALTER TABLE student ADD ad_id INT COMMENT 'fk ref advisor';
Further, some storage engines, like InnoDB, support and enforce foreign keys. That is, we can have the database enforce restrictions (constraints) on values that can be stored in columns defined as foreign keys.
For example, we can establish a rule that says that a value stored in the ad_id column in the student table... must be found in a row in the advisor table, in the ad_id column.
For example:
ALTER TABLE student ADD CONSTRAINT fk_student_advisor
FOREIGN KEY (ad_id) REFERENCES advisor(ad_id)
ON DELETE RESTRICT ON UPDATE CASCADE
This also enforces a rule that a row from advisor table cannot be deleted if there are rows in student table that reference it.
That same pattern can be repeated for any one to-to-many relationship. For example, if a student can be related to at most one section we can add a foreign key in the same way.
If there's a many-to-many relationship, then we introduce a relationship table that has foreign keys referencing the two related entity tables.
If a student can be related to zero, one or more section, and a section can be related to zero, one or more student, that's an example of a many-to-many relationship.
We can introduce a new table like this (as an example):
CREATE TABLE student_section
( student_id INT NOT NULL COMMENT 'pk, fk ref student'
, section_id INT NOT NULL COMMENT 'pk, fk ref section'
, PRIMARY KEY (student_id, section_id)
, CONSTRAINT fk_student_section_student
FOREIGN KEY student_id REFERENCES student(s_id)
ON DELETE CASCADE ON UPDATE CASCADE
, CONSTRAINT fk_student_section_section
FOREIGN KEY section_id REFERENCES section(sec_id)
ON DELETE CASCADE ON UPDATE CASCADE
)
With that in place, to establish a relationship between a student and a section, we insert a row to the new student_section table. If the student is related to another section, we add another row to the table, referencing the same student, but a different section.
The value stored in the student_id column refers to a row in the student table; and a value stored in the section_id column refers to a row in the section table.
(The many-to-many relationship is really composed of rows in a new table that has a one-to-many relationship to two other tables.)

Can I have a one to many relationship between a primary key in one table and a primary key in a second table?

Whenever i try to create a one to many relationship between two tables, i realized that it is only working if i have the relationship between a primary key in table one an element which is not a primary key in table two. If it has a primary key then it automatically changes to a one to one relationship
Can I have a one to many relationship between a primary key in one table and a primary key in a second table?
No, because the Primary Key values in each table must be unique so there is no way that you could have multiple values of the same Primary Key in either table. We can (and usually do) establish a one-to-many relationship between the Primary Key in one table (the "parent table") and a Foreign Key in the other ("child") table, where the Foreign Key in the child table holds the Primary Key value from the parent table.
Example:
[tblCustomers]
CustomerID CompanyName
---------- -----------
1 Company1
2 Company2
[tblInvoices]
InvoiceID CustomerID InvoiceDate
--------- ---------- -----------
1 1 2014-07-21
2 1 2014-08-25
3 2 2014-08-28
We establish the one-to-many relationship between tblCustomers.CustomerID (the Primary Key in the [tblCustomers] "parent" table) and tblInvoices.CustomerID (the Foreign Key in the [tblInvoices] "child" table). tblInvoices.CustomerID is not unique because there can be many invoices for the same customer.
Note that if you were to try and establish a relationship between tblCustomers.CustomerID (the Primary Key in the [tblCustomers] "parent" table) and tblInvoices.InvoiceID (the Primary Key in the [tblInvoices] "child" table) then that relationship would have to be a one-to-one relationship. It would also be meaningless.
This is expected behaviour. The primary key must be unique, so if you join two primary keys together, then the relationship must be one-to-one.

Combining Foreign Keys

In MySQL, how do you combine 2 foreign keys in a table to become a primary key?
I have two tables, one Staff, one Roles, each containing their own primary keys, StaffID and RoleID. I have created a third table called StaffRole which will contain the StaffID and RoleID, keeping in mind this is a one to many relationship, as a staff member may have 1 or more roles.
How would you combine the foreign key of StaffID and RoleID to create a new unique primary keys for the table StaffRole.
Technically, what you are describing is not a one-to-many relationship, but instead it is a many-to-many relationship since one Staff record relates to many Role records, but one Role record also relates to many different Staff. Your use of the join table StaffRole is the typical way of handling the relationship.
This is semantics, but it isn't really a matter of combining the two foreign keys, so much as just creating a third key which is the composite of the two and also the primary key. So your table will have two FOREIGN KEY definitions, one each for the two columns, and one composite PRIMARY KEY definition across both of the columns.
CREATE TABLE StaffRole (
StaffID INT NOT NULL,
RoleID INT NOT NULL,
/* Composite primary key on both columns */
PRIMARY KEY (StaffID, RoleID),
/* Two separate foreign keys */
FOREIGN KEY (StaffID) REFERENCES Staff (StaffID),
FOREIGN KEY (RoleID) REFERENCES Roles (RoleID)
) ENGINE=InnoDB;
Note, I have specified InnoDB as the table type, since MySQL will not enforce the FOREIGN KEYs on MyISAM tables.
You can create a StaffRoleID as a primary key, and use StaffID and RoleID as foreign keys.