简体   繁体   中英

Clarification - Default Foreign Key Constraints - InnoDB

MySQL Server version: 5.6.17 I have two tables:

vatbands:

`vatbands_id` INT(11) UNSIGNED NOT NULL,
`client_id` INT(11) UNSIGNED NOT NULL COMMENT 'Customer ID',
`code` ENUM('A', 'B', 'C', 'D', 'E', 'F') NOT NULL,
PRIMARY KEY (`vatbands_id`, `code`, `client_id`),
INDEX `vatcode_vatbands` (`code` ASC, `client_id` ASC)
ENGINE = InnoDB;

1 row in vatbands:

INSERT INTO `vatbands` (`client_id`, `code`) VALUES ('1', 'A');

items:

`client_id` INT(11) UNSIGNED NOT NULL,
`vatcode` ENUM('A', 'B', 'C', 'D', 'E', 'F') NOT NULL DEFAULT 'A',
PRIMARY KEY (`item_id`, `client_id`),
INDEX `vatcode_item` (`vatcode` ASC, `client_id` ASC),
  CONSTRAINT `vatcode_item`
    FOREIGN KEY (`vatcode` , `client_id`)
ENGINE = InnoDB;

Inserting into child (item) table:

INSERT INTO `item` (`client_id`, `code`) VALUES ('1', '');

When I try to insert into my items table without specifying a vatcode i get foreign key constraint failure:

Cannot add or update a child row: a foreign key constraint fails (`mydb`.`item`, CONSTRAINT `vatcode_item` FOREIGN KEY (`vatcode`, `client_id`) REFERENCES `vatbands` (`code`, `client_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

Why is this, I thought specifying a default value for the vatcode would allow this to continue (as long as the row exists)?

I have checked the InnoDB manual:

14.6.6 InnoDB and FOREIGN KEY Constraints

Referential actions for foreign keys of InnoDB tables are subject to the following conditions:

While SET DEFAULT is allowed by the MySQL Server, it is rejected as invalid by InnoDB.

Is this the reason it is failing?

UPDATE:

If i input a value directly using PHP:

INSERT INTO `item` (`client_id`, `code`) VALUES ('1', 'A');

The constraint succeeds as expected.

The SET DEFAULT clause for a foreign key has nothing to do with inserting to the child table. It declares what to do with dependent rows in the child table if the referenced row in the parent table is deleted or updated.

Example: If an employee belongs to a department, and the department is deleted, should the employee be fired as well? Or should they be reassigned to some other "default" department?

I tested your example, and I find that it works fine, but you must specify at least a client_id that exists in the parent table.

mysql> insert into items (client_id) values (1);
Query OK, 1 row affected (0.00 sec)

I also notice that your key in vatbands on (code,client_id) is a non-unique key. It should really be a primary key or unique key to be referenced by a foreign key of a child table. In fact, when I test with MySQL 5.7 milestone release, I can't even create the items table because apparently in this regard the new version of MySQL is more strict than older versions. So I had to make your key a primary key. Then the test worked.

The only way I could get this to work is inserting a default using PHP.

INSERT INTO `item` (`client_id`, `code`) VALUES ('1', 'A');

If anyone has any better ways of resolving this please don't hesitate to comment, I would much prefer a pure MySQL method.

If you use:

INSERT INTO `item` (`client_id`, `code`) VALUES ('1', '');

You are not inserting NULL but an empty string.

INSERT INTO `item` (`client_id`, `code`) VALUES ('1', NULL);

will work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM