【问题标题】:Clarification - Default Foreign Key Constraints - InnoDB澄清 - 默认外键约束 - InnoDB
【发布时间】:2014-09-20 01:06:18
【问题描述】:

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;

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', '');

当我尝试插入我的项目表而不指定 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 和外键约束

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

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

这是失败的原因吗?

更新:

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

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

约束按预期成功。

【问题讨论】:

  • SET DEFAULT 指的是外键约束操作:... ON DELETE SET DEFAULT
  • 请发sqlfiddle.com 并在此处发布链接。
  • @rcdmk 好的,有道理,谢谢。
  • @rcdmk 构建模式正在花时间得到“数据截断错误”,如果这有帮助吗? - 我可以发布。
  • @rcdmk 我无法让 sqlfiddle 构建架构,它只是挂起...a timeout occurred on a exclusive lock with name [2_ed990] after 60 seconds 这是我所得到的(缺少可以在我的问题)sqlfiddle.com/#!2/a9f00

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


【解决方案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 比旧版本更严格。所以我不得不让你的钥匙成为主钥匙。然后测试成功了。

【讨论】:

  • 嗨,比尔,我在两个表中都将 client_d 指定为“1”,将更新我的问题。
  • 那么让它成为父表中的主键/唯一键怎么样?
  • 是的,它已经是父表中的主键,我会更新我的问题。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    如果你使用:

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

    您插入的不是 NULL,而是一个空字符串。

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

    会起作用

    【讨论】:

    • 嗨 Gervs,这是我尝试的第一件事!再试一次,干杯。
    • 所以该列设置为 NN,我得到了 column vatcode cannot be null,所以我将其更改为可为空的字段,现在它只是将 NULL 插入该字段 - 忽略 DEFAULT 值。 ..
    猜你喜欢
    • 2014-06-23
    • 2016-03-19
    • 2010-12-07
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-14
    相关资源
    最近更新 更多