how do foreign key works in MYSQL? - mysql

So i have read here that MyISAM is the default engine for MYSQL and it does not support foreign keys, But i have created a table just now and forgot to put ENGINE=INNODB, it still have my defined foreign key. My MySQL version is 14.14 by the way. And i used this code to make my foreign key:
CREATE TABLE my_table (
my_foreign_key_fk INT NOT NULL,
FOREIGN KEY (my_foreign_key_fk) REFERENCES sometable(primary_key_pk)
);
and here's how i checked and assumed that my foreign key were implemented:
DESC my_table
which displayed like this on the key column:
Field |Key
------------------|----
my_foreign_key_fk |MUL
So can someone enlighten me on this one?

With MyISAM you can create the FK, it just doesn't do anything, such as support referential integrity.

Related

Confused about foreign key constraint

I have a general question about constraint.
What are the difference between the following examples?
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
OrderNumber int NOT NULL,
PersonID int FOREIGN KEY REFERENCES Persons(PersonID)
);
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
REFERENCES Persons(PersonID)
);
Thank you!
There is no logical difference.
Standard SQL supports both forms of declaring constraints: at the column level, as in your first example, and at the table level, in your second example.
Table level constraint syntax is needed if you have a primary key or foreign key that involves more than one column.
MySQL supports both column-level and table-level syntax for PRIMARY KEY. But if you subsequently run SHOW CREATE TABLE Orders you will see that MySQL reports it back as if it was declared as a table-level constraint.
MySQL supports only table-level syntax for FOREIGN KEY.
It has been a long-time feature request to support column-level FOREIGN KEY syntax, but so far it has not been implemented. https://bugs.mysql.com/bug.php?id=4919
In the first example, The database will name the constraints implicitly.
In the second example, the create table statement sets the name of the foreign key constraint explicitly. (the primary key should also be named but it's not in this example)
As best practice, you should always give your constraints meaningful names.

purpose of declaring foreign keys in mysql MyISAM engine

I just came to know that mysql MyISAM engine doesn't support foreign keys.But i have seen several example of declaring foreign keys like below :
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
As foreign keys are not supported we would not get the benefits like on update and on delete in MyISAM engine.My question is then why we are declaring a field as foreign key in MyISAM engine ?
There is no point of declaring foreign keys with the myisam table type, since this functionality does not exist there. Mysql can parse the foreign key syntax for the myisam table type (meaning no error message will be raised if it encounters an fk definition), making migration from other database products or table engines easier because you do not have to edit the create table statements to remove them.

Unable to add two foreign keys to a table

I have two tables as follow:
1st Table:
CREATE TABLE User (
User_ID VARCHAR(8)NOT NULL PRIMARY KEY,
User_Name VARCHAR (25) NOT NULL,
User_Gender CHAR (1) NOT NULL,
User_Position VARCHAR (10) NOT NULL,
);
2nd table:
CREATE TABLE Training (
Training_Code VARCHAR(8) NOT NULL Primary Key,
Training_Title VARCHAR(30) NOT NULL,
);
I am trying to create a table which has two foreign keys to join both of the previous tables:
CREATE TABLE Request (
User_ID VARCHAR(8) NOT NULL,
Training_Code VARCHAR(8) NOT NULL,
Request_Status INT(1) NOT NULL
);
When I am trying to set the foreign keys in the new table, the User_ID can be done successfully but the Training_Code cannot be set to foreign key due to the error:
ERROR 1215 (HY000): Cannot add foreign key constraint
As I searched for this problem, the reason for it, is that data type is not the same, or name is not the same.. but in my situation both are correct so could you tell me what is wrong here ?
You need an index for this column in table Request too:
Issue first
CREATE INDEX idx_training_code ON Request (Training_Code);
Then you should be successful creating the foreign key constraint with
ALTER TABLE Request
ADD CONSTRAINT FOREIGN KEY idx_training_code (Training_Code)
REFERENCES Training(Training_Code);
It worked for me. But I've got to say that it worked without create index too, as the documentation of Using FOREIGN KEY Constraints states:
MySQL requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. In the
referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist. This index might be silently dropped later, if you create
another index that can be used to enforce the foreign key constraint.
index_name, if given, is used as described previously.
Emphasis by me. I don't know what's the issue in your case.
Demo
Explanation of the issue
The behavior mentioned in the question can be reproduced if the table Training is using the MyISAM storage engine. Then creating a foreign key referencing the table Training will produce the mentioned error.
If there's data in the table, then simple dropping of the table would not be the best solution. You can change the storage engine to InnoDB with
ALTER TABLE Training Engine=InnoDB;
Now you can successfully add the foreign key constraint.

I am getting an error trying to create table in phpmyadmin

I am trying to run the following:
CREATE TABLE IF NOT EXISTS table_name (
user_id int(11) NOT NULL,
other_id int(11) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (other_id) REFERENCES other_table(id),
PRIMARY KEY (user_id, other_id)
);
and getting the following error:
#1005 - Can't create table 'database_name.table_name' (errno: 150)
am I doing something wrong? This works fine just running it in another environment rather than phpmyadmin sql environment.
Take a look at this SO question.
Note the correct answer. Check column types They need to match. May be your problem.
In general, Here is the authoritative guide to FK in Mysql.
In addition to SHOW ERRORS, in the event of a foreign key error
involving InnoDB tables (usually Error 150 in the MySQL Server), you
can obtain a detailed explanation of the most recent InnoDB foreign
key error by checking the output of SHOW ENGINE INNODB STATUS.
EDIT: Incorporating comments
Table on PHPMyAdmin were defaulting to MyISAM. On Local they were defaulting to to InnoDB. MyISAM does not support FK. This does not fully explain the difference, as based on MySql Documentation, It should just work, without creating the FK's. ( Perhaps a settings issue or Older Version Issue)
Does users and other_table exist?
You can't have the foreign key references to non-existant tables.
You can add the references afterwards with alter table.
DROP TABLE IF EXISTS `table_name`;
CREATE TABLE IF NOT EXISTS table_name (
user_id int(11) NOT NULL,
other_id int(11) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (other_id) REFERENCES other_table(id),
PRIMARY KEY (user_id, other_id)
);

Failure in using alter table to add partition

I have a table having structure as below:
CREATE TABLE `child_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`value` int,
`ref_id` int,
PRIMARY KEY (`id`),
KEY `ref_id` (`ref_id`),
CONSTRAINT `FK4E9BF08E940F8C98` FOREIGN KEY (`ref_id`) REFERENCES `parent_table` (`id`) ON DELETE CASCADE
)
When running statement to add partition, it fails and show the error:
ERROR 1217: Cannot delete or update a parent row: a foreign key constraint fails
SQL Statement:
ALTER TABLE `learning`.`child_table` PARTITION BY HASH(ref_id) PARTITIONS 10
So I remove the foreign constraint with parent_table, then run again. It still fails and show the same error.
Did I do anything wrong?
I know this is an old question, but for people that fall here from looking for this problem, since its the first Google result:
MySQL does not support foreign keys on partitioned tables.
From the manual
Foreign keys not supported for partitioned InnoDB tables. Partitioned tables using the InnoDB storage engine do not support foreign keys. More specifically, this means that the following two statements are true:
No definition of an InnoDB table employing user-defined partitioning may contain foreign key references; no InnoDB table whose definition contains foreign key references may be partitioned.
No InnoDB table definition may contain a foreign key reference to a user-partitioned table; no InnoDB table with user-defined partitioning may contain columns referenced by foreign keys.
The error is referring to a foreign key on another table that references child_table. You need to find and remove the foreign key from that table, not necessarily child_table. You could also try running SET foreign_key_checks = 0 first.