澄清 - 默认外键约束 - InnoDB

时间:2014-09-20 01:06:18

标签: mysql sql foreign-keys innodb default-value

MySQL服务器版本:5.6.17 我有两张桌子:

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;

vatbands中的1行:

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

项目:

`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;

插入子(项)表:

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

当我尝试插入我的items表而没有指定vatcode我得到外键约束失败时:

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)

为什么这样,我认为指定vatcode的默认值会允许它继续(只要该行存在)?

我查看了InnoDB手册:

  

14.6.6 InnoDB和FOREIGN KEY约束

     

InnoDB表的外键的引用操作受制于   以下条件:

     

虽然MySQL服务器允许SET DEFAULT,但它被拒绝为   InnoDB无效。

这是它失败的原因吗?

更新

如果我直接使用PHP输入值:

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

约束按预期成功。

3 个答案:

答案 0 :(得分:1)

外键的SET DEFAULT子句与插入子表无关。它声明如果删除或更新父表中引用的行,如何处理子表中的从属行。

示例:如果员工属于某个部门,并且该部门被删除,员工是否也应被解雇?或者他们应该被重新分配到其他一些"默认"部?

我测试了您的示例,我发现它工作正常,但您必须至少指定父表中存在的client_id

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

我还注意到你的密码输入(code,client_id)是非唯一密钥。它应该是子表的外键引用的主键或唯一键。事实上,当我使用MySQL 5.7里程碑版本进行测试时,我甚至无法创建items表,因为在这方面显然MySQL的新版本比旧版本更严格。所以我必须让你的钥匙成为主键。然后测试工作。

答案 1 :(得分:0)

我能让它工作的唯一方法是使用PHP插入默认值。

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

如果有人有更好的方法可以解决这个问题,请不要犹豫评论,我更喜欢纯粹的MySQL方法。

答案 2 :(得分:0)

如果您使用:

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

您不是插入NULL而是空字符串。

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

将起作用