What are MySQL foreign keys? - mysql

In an answer on Stack Overflow, I saw this code:
CREATE TABLE Favorites (
user_id INT NOT NULL,
movie_id INT NOT NULL,
PRIMARY KEY (user_id, movie_id),
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
I've never used the 'foreign key' relationship keyword before.
What is it?
Why do people use it?
Does it provide any benefit apart from semantics?

A foreign key is a reference to a primary key in another table or the table itself. It is used for what is called referential integrity. Basically in your table provided, for a Record to be inserted into Favorites - you would have to supply a valid user_id from the Users table, and a valid movie_id from the Movies table. With Foreign keys enforces, I could not delete a record from Users or Movies. If I didn't have foreign keys, I could delete those records. Then if I did a SELECT ... JOIN on Favorites it would break.
See Wikipedia.

A foreign key describes a relationship between two tables. It has many benefits:
You can enforce that if a value is in the one table then it must also exist in the other table. Any attempt to break this constraint will give an error.
It allows database administrators or programmers to more easily understand the relationship between the tables just by looking at the table definitions.
It allows tools to inspect the schema and draw diagrams showing the relations between the tables, or create classes where the children of an object are accessible from the parent via members.
In InnoDB adding a foreign key also automatically adds an index on that column so that the join can be made efficiently in either direction. (Source)
If you are using MyISAM then foreign keys are not supported.

You can also add the ability to cascade when a related record is deleted. For example if I have a library table with many books in a related "book" table and I delete a given library from my library table its' dependent book records will also be deleted.

Related

Is table order imporant in mysql when creating relation between them?

I have quite simple question. I am creating database administration tool, where user will be able to create relations between tables, but I am not sure if table order is important when creating relations.
For example: I have two tables 'user'(user_id(INT, PRIMARY KEY), name(VARCHAR), email(VARCHAR)) and 'post'(post_id(INT, PRIMARY KEY), content(TEXT), author(INT)).
When user has selected one column from both tables ('user'(user_id) and 'post'(author)) tool creates a query:
ALTER TABLE 'user' ADD CONSTRAINT 'user_id_to_author' FOREIGN KEY ('user_id') REFERENCES post('author')
but if user would select tables in different order ('post'(author) and 'user'(user_id)) then query would look like this:
ALTER TABLE 'post' ADD CONSTRAINT 'author_to_user_id' FOREIGN KEY ('author') REFERENCES user('user_id')
Is there any difference between both query's and if so whats is it?
You are defining a one-to-many relationship, so the direction of the relationship does matter.
The table that is altered is the child table; many rows may refer to the parent table, through the primary key of the parent table.
For the example given here, a post belongs to a user, and many posts may have the same author, so you want:
ALTER TABLE post
ADD CONSTRAINT author_to_user_id
FOREIGN KEY (author) REFERENCES user(user_id)
Note that object names should not be surrounded with single quotes.
Trying to create the relationship the other way around does not make sense. It would imply that a user needs to have a post before it can be created.

Am I supposed to use foreign keys for these 3 tables which are connected?

So I have 3 tables:
Table: Albums
Columns: Id, Name, Description, Author, Folderpath, Thumbnail, Upvotes, Downvotes
Table: AlbumsConnection
Columns: Id, AlbumId, AlbumImagesId
Table: AlbumImages
Columns: Id, InAlbum, Imagepath
So far I've been using these tables without actually using foreign keys. Am I supposed to use foreign keys here? I understand that I'd have to add 2 foreign keys to AlbumsConnection, 1 for each table and each foreign key will reference to the primary keys ( which are the ids ) of the other 2 tables. Is that correct?
Foreign keys help ensure relational integrity of the database. There is no requirement for declaring them explicitly, but it is a good idea, particularly if you are learning to use databases.
The foreign key let's the database know that a column in one table is related to a column in another table. I don't think MySQL's optimizer uses this information explicitly, although it does create an index on the foreign key column (unlike most other databases).
In addition, a declared foreign key relationship can help you deal with changes to the database. It will prevent invalid albums from being inserted into the junction table. If you delete an album, it gives you control over how the deletion and updating is handled (via cascading constraints).

How to refer to different tables from one column?

i have following db design(kept just essential informations):
TABLE monument
PRIMARY KEY id
name
TABLE restorer
PRIMARY KEY id
name
TABLE project
PRIMARY KEY id
name
TABLE restorer2project
FOREIGN KEY restorer_id REFERENCES restorer(id),
FOREIGN KEY project_id REFERENCES project(id)
PRIMARY KEY (restorer_id, restoration_project_id)
TABLE monument2project
FOREIGN KEY monument_id REFERENCES monument(id)
FOREIGN KEY project_id REFERENCES project(id)
PRIMARY KEY (monument_id, project_id)
Project can have many restorers and have many monuments.Also project can repeat in future with same relations, but different date.
I want to create table witch will store pictures.
TABLE picture
PRIMARY KEY id
reference_to_different_tables
Is it possible point to different tables from one column?
if yes how?
Is this good design (fro me it is natural i can imagine to create more tables with pictures)
Other approach is to have references to pictures from other tables, but then i will need some kind of mapping table, but not sure if it is also good design.
From database prespective you can't have a foreign referring to different tables.
It can refer to one table at a time.
There can be three solutions I can think of:
The best solution in my opinion is to have a parent table say artifact to monument, restorer and project. The later three tables will have primary key as foreign key from artifact table. This way you can have single column in picture table which will refer to artifact table.
Or you can specify multiple columns in picture table as suggested by #CptMisery in the comments.
Create multiple picture table for all of them. This is not considered as good solution.
If you are using any persistence framework than the first solution can solve dynamic query problem as well.

Use of Primary Key as Foreign Key in Foreign Key Table

This may sound confusing and or simple but..
If I use a foreign key from Table B in Table A, which has a separate primary key. Do I need to include Table A's primary key as a foreign key in Table B?
Thanks!
========================================================================
EDIT:
Okay, let me try and clarify my question a bit.
In the case above, should I use Taco_ID as a FK in Table 2? Or is does it completely unnecessary?
In general, you don't usually make foreign keys bidirectionally like that. If you do, it means that the two tables exist in a 1-to-1 relationship: Each taco has a type, and each taco type can only be used by one taco. If you have a relationship like this, there's not really any reason to have them in separate tables, they could just be additional columns in the same table.
Normally foreign keys are used for 1-to-many or many-to-many relationships.
A 1-to-many relationship would be if many different tacos can be of the same type. They each have Taco_Type_ID foreign key.
For a many-to-many relationship, you typically use a separate relation table.
CREATE TABLE Taco_Types (
Taco_ID INT, -- FK to Table1.Taco_ID
Taco_Type_ID INT, -- FK to Table2.Taco_Type_ID
PRIMARY KEY (Taco_ID, Taco_Type_ID)
);
foreign keys and primary keys are SOMETIMES related, but not always. A foreign key in a table literally just means "whatever value is in this field MUST exist in this other table over ---> here". Whether that value is a PK or not in that other table is irrelevant - it just has to exist, and it has to be unique. That may fit the bill of being a primary key, but being primary is NOT required.
You can have composite foreign keys, e.g. in a (silly) address book, the child table you list a person's phone numbers in COULD be keyed with (firstname, lastname), but that runs into the problem of "ok, which John Smith does this number belong to?".
In most databases, foreign key references must be to primary keys or unique keys (and NULLs are allowed). MySQL recommends this but does not require it:
However, the system does not enforce a
requirement that the referenced columns be UNIQUE or be declared NOT
NULL. The handling of foreign key references to nonunique keys or keys
that contain NULL values is not well defined for operations such as
UPDATE or DELETE CASCADE. You are advised to use foreign keys that
reference only UNIQUE (including PRIMARY) and NOT NULL keys.
Do you need to reference primary keys for a foreign key relationship? First, you don't even need to declare foreign key relationships. I think they are important because they allow the database to maintain referential integrity. But, they are not required. Nor is there any semantic difference in queries, based on the presence of foreign keys (for instance, NATURAL JOIN does not use them). The optimize can make use of the declared relationship.
Second, if you are going to declare the foreign key, I would recommend using the primary key of the referenced table. That is, after all, one of the major reasons for having primary keys.

Is it safe to add foreign key constraint on two columns, while one is not unique (MySQL)?

I have a users table and other tables such as services, orders, etc... that are I would like to turn into child tables of the users table.
So far it's simple, I just add Foreign Key Constraint between users(id) and orders(user_id). But what if I'd like to add a Boolean users(disabled) field, that would cascade the update to the orders(disabled) and services(disabled) fields in the rows that reference the respective row in users via (user_id) key?
Would it work if I create a reference in the child table to the parent table using 2 keys, one primary and one non unique?
You could have probably answered your question yourself if you'd have tried it. Basically, you can't create a foreign key relation on columns that are not part of a primary key on the foreign table (as the name implies).
So, unless the disabled column is part of the primary key on the users table, then, no, you won't be able to create a foreign key relation in another table that would include the disabled column.
All is not lost though. You could use triggers to trigger the disabling of orders and services when a user becomes disabled.