Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
10.5.27, 10.6.20, 10.11.10, 11.2.6, 11.4.4
Description
After upgrading to v10.11.10 creation of a foreign key failed with no information in engine innodb status. The same keys are allowed in 10.11.9 and below.
reproducer SQL:
CREATE TABLE `a` (
|
`a_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`a_p_id` int(10) unsigned DEFAULT NULL,
|
PRIMARY KEY (`a_id`),
|
FOREIGN KEY (`a_p_id`) REFERENCES `a` (`a_id`)
|
) ENGINE=InnoDBa
|
|
|
CREATE TABLE `b` (
|
`b_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`b_p_id` int(10) unsigned DEFAULT NULL,
|
PRIMARY KEY (`b_id`),
|
FOREIGN KEY (`b_p_id`) REFERENCES `b` (`b_id`)
|
) ENGINE=InnoDB
|
|
|
CREATE TABLE `b_a` (
|
`b_id` int(10) unsigned NOT NULL,
|
`a_p_id` int(10) unsigned NOT NULL,
|
`a_id` int(10) unsigned DEFAULT NULL,
|
PRIMARY KEY (`b_id`,`a_p_id`),
|
FOREIGN KEY (`b_id`) REFERENCES `b` (`b_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
FOREIGN KEY (`a_p_id`, `a_id`) REFERENCES `a` (`a_p_id`, `a_id`) ON UPDATE CASCADE
|
) ENGINE=InnoDB
|
Changing the table b_a latest foreign key to "on delete cascade" does allow the table to be created, but that is not what I want to archieve.
Attachments
Issue Links
- is caused by
-
MDEV-34392 modification of the column fails to check foreign key constraint
-
- Closed
-
dicode, if I understood this correctly, you are intentionally using such a schema and indeed prefer to have a DML time error instead of a DDL time error. I agree that we should revise this.
One possible fix could be that if sql_mode does not include STRICT_ALL_TABLES or STRICT_TRANS_TABLES, we would ignore any ON UPDATE inconsistency that is related to the referencing column being declared as NOT NULL.
When it comes to ON UPDATE SET NULL, I can imagine that someone might want to (ab)use them as a kind of a stricter FOREIGN KEY constraint, not allowing any change in the parent table as long as a referencing record in a child table (with NOT NULL on that column) exists.
I do not see any reason to allow ON DELETE SET NULL when the referencing column is declared NOT NULL. The same effect (prohibiting DELETE of the referenced row if a referencing row exists) would be achieved without defining any ON DELETE SET NULL.
I tested the following variant of your example:
--source include/have_innodb.inc
) ENGINE=InnoDB;
) ENGINE=InnoDB;
As far as I understand, you would want the original DDL to go through and the UPDATE statement to fail due to a foreign key constraint violation, because the record (1,3,4,4) cannot be updated to (1,NULL,4,4), since f_fg.fg_p_id is declared NOT NULL.
Above, I "fixed" the DDL by removing the NOT NULL and by omitting a PRIMARY KEY in f_fg (all PRIMARY KEY columns are implicitly NOT NULL). Note: Omitting a PRIMARY KEY is a bad idea if you are using any replication; see MDEV-21181. InnoDB would add a hidden internal 48-bit column DB_ROW_ID that acts as the primary key, but it would not be visible outside InnoDB. It would be better to add an AUTO_INCREMENT PRIMARY KEY if one wanted to go this route.