purpose of declaring foreign keys in mysql MyISAM engine - mysql

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.

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.

Separate FOREIGN KEY declaration fails

The following CREATE TABLE statement (simplified on purpose)
works well on current Mysql 5.1 / INNODB:
CREATE TABLE Employee (
id INT NOT NULL PRIMARY KEY
,boss INT REFERENCES Employee
)
Now I try to create the FOREIGN KEY separately (after executing DROP TABLE Employee):
CREATE TABLE Employee (
id INT NOT NULL PRIMARY KEY
, boss INT
,CONSTRAINT _FK_boss FOREIGN KEY(boss) REFERENCES Employee
)
This time table creation fails with message
"Cannot add foreign key constraint".
BTW: I already did a DROP/CREATE DATABASE ..., tinkered with the constraint identifier name with no success at all. Adding an explicit "Engine innodb" does not help either. My original schema has two distinct 1:n related tables exhibiting identical behavior.
As far as I understand
http://dev.mysql.com/doc/refman/5.1/en/create-table.html the syntax is alright.
The first example did not work. If you run SHOW CREATE TABLE, you'll see the constraint is not there.
MySQL parses inline foreign key declarations, but InnoDB ignores them. InnoDB supports only table-level constraints. And InnoDB requires the column to be declared explicitly, even though standard SQL says it's optional.
This is an artifact of MySQL's pluggable storage engine architecture. Both the storage-independent layer of MySQL and each individual storage-engine layer has their own SQL parser, and they may not agree on how much of the standard language they support. Another example is CHECK constraints, which are parsed by MySQL, but ignored by all storage engines (so far).
Foreign key constraints require the column; it's not optional. This statement will allow the declaration to succeed.
CREATE TABLE Employee (
id INT NOT NULL PRIMARY KEY
, boss INT
,CONSTRAINT _FK_boss FOREIGN KEY(boss) REFERENCES Employee (id)
);

Supports transactions, row-level locking, and foreign keys

For some reason I cannot create this table:
CREATE TABLE user_role (
user_id VARCHAR(20) NOT NULL,
role_id INTEGER UNSIGNED NOT NULL,
FOREIGN KEY (user_id)
REFERENCES users(user_id),
FOREIGN KEY (role_id)
REFERENCES roles(role_id)
);
The following similar table has no problems:
CREATE TABLE role_perm (
role_id INTEGER UNSIGNED NOT NULL,
perm_id INTEGER UNSIGNED NOT NULL,
FOREIGN KEY (role_id)
REFERENCES roles(role_id),
FOREIGN KEY (perm_id)
REFERENCES permissions(perm_id)
);
The error message I'm getting is:
#1005 - Can't create table 'test.user_role' (errno: 150) (Details...)
Supports transactions, row-level locking, and foreign keys
Any ideas?
See http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
If you re-create a table that was dropped, it must have a definition that conforms to the foreign key constraints referencing it. It must have the correct column names and types, and it must have indexes on the referenced keys, as stated earlier. If these are not satisfied, MySQL returns Error 1005 and refers to Error 150 in the error message, which means that a foreign key constraint was not correctly formed.
If is rather difficult to guess as you didn't provide the definitions for the roles and permissions tables but to paraphrase the doc...
...in order to have a foreign key on a column, you must have an index on the "target" column.
...in order to have a foreign key on a column, both "source" and "target" columns must have the same type (incl. the same size if applicable).
...in order to have a foreign key on a column, both tables must use InnoDB engine.
For my case, I handle several databases, when I try to create the table it returned this error "transactions, row-level locking, and foreign keys", the error occurred because the relationship table did not exist,
casually it recognized it from another database where the table did exist, but i have only creating the relationship table to solve the problem.
I took into account the recommendations of relations given in this forum because it also has to do with the version of MySql.

how do foreign key works in 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.

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.