MYSQL 错误 1823 当 SET FOREIGN_KEY_CHECKS=1

Posted

技术标签:

【中文标题】MYSQL 错误 1823 当 SET FOREIGN_KEY_CHECKS=1【英文标题】:MYSQL ERROR 1823 When SET FOREIGN_KEY_CHECKS=1 【发布时间】:2017-07-04 13:36:08 【问题描述】:

我有一个奇怪的错误,当 FOREIGN_KEY_CHECKS = 0 和 2 个查询被执行(除了 FOREIGN_CHECK_CHECKS 之外,这两种情况都一样。

该错误导致错误 ERROR 1823 (HY000): Failed to add the foreign key constraint...(以下为完整错误)

如果我使用 SET FOREIGN_KEY_CHECKS=1 运行查询,它会按预期工作。 (这似乎是反话,因为关闭外键检查应该让事情过去,但不应该)

这是 mysql 中的错误还是我不明白?我找不到关于这个 mysql 错误代码的太多信息。

MYSQL 版本: 5.6.33

错误(最后一个查询):

mysql> SET FOREIGN_KEY_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE phppos_people ADD INDEX phppos_people_ibfk_1 (image_id);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE phppos_customers ADD CONSTRAINT phppos_customers_ibfk_1 FOREIGN KEY person_id (person_id) REFERENCES phppos_people (person_id) ON UPDATE NO ACTION ON DELETE NO ACTION;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE phppos_employees ADD CONSTRAINT phppos_employees_ibfk_1 FOREIGN KEY person_id (person_id) REFERENCES phppos_people (person_id) ON UPDATE NO ACTION ON DELETE NO ACTION;
ERROR 1823 (HY000): Failed to add the foreign key constraint 'migrate/person_id' to system tables

成功:

mysql> SET FOREIGN_KEY_CHECKS=1;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE phppos_people ADD INDEX phppos_people_ibfk_1 (image_id);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE phppos_customers ADD CONSTRAINT phppos_customers_ibfk_1 FOREIGN KEY person_id (person_id) REFERENCES phppos_people (person_id) ON UPDATE NO ACTION ON DELETE NO ACTION;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE phppos_employees ADD CONSTRAINT phppos_employees_ibfk_1 FOREIGN KEY person_id (person_id) REFERENCES phppos_people (person_id) ON UPDATE NO ACTION ON DELETE NO ACTION;
Query OK, 1 row affected (0.04 sec)
Records: 1  Duplicates: 0  Warnings: 0

架构:

mysql> show create table phppos_people;
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table         | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_people | CREATE TABLE `phppos_people` (
  `first_name` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `last_name` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `phone_number` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `email` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `address_1` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `address_2` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `city` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `state` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `zip` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `country` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `comments` text CHARACTER SET ucs2 NOT NULL,
  `image_id` int(11) DEFAULT NULL,
  `person_id` int(11) NOT NULL,
  PRIMARY KEY (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show create table phppos_customers;
+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table            | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_customers | CREATE TABLE `phppos_customers` (
  `id` int(11) NOT NULL,
  `person_id` int(11) NOT NULL,
  `account_number` varchar(255) CHARACTER SET ucs2 DEFAULT NULL,
  `override_default_tax` int(11) NOT NULL,
  `company_name` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `balance` decimal(23,10) NOT NULL,
  `credit_limit` decimal(23,10) DEFAULT NULL,
  `points` decimal(23,10) NOT NULL,
  `current_spend_for_points` decimal(23,10) NOT NULL,
  `current_sales_for_discount` int(11) NOT NULL,
  `taxable` int(11) NOT NULL,
  `tax_certificate` varchar(255) CHARACTER SET ucs2 NOT NULL,
  `cc_token` varchar(255) CHARACTER SET ucs2 DEFAULT NULL,
  `cc_preview` varchar(255) CHARACTER SET ucs2 DEFAULT NULL,
  `card_issuer` varchar(255) CHARACTER SET ucs2 DEFAULT NULL,
  `tier_id` int(11) DEFAULT NULL,
  `deleted` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

【问题讨论】:

【参考方案1】:

得到相同的错误号:1823;符号:ER_FK_FAIL_ADD_SYSTEM; SQLSTATE: HY00063 消息:无法将外键约束“%s”添加到系统表

在我的情况下,当我减少查询起作用的约束名称的长度时,FK 名称太长了。

【讨论】:

【参考方案2】:

是的,这似乎是一个错误。我可以在 MySQL 5.6+ 中验证它(以及在 MySQL 8 中类似的东西),而 5.5 不受影响。这里的问题是 MySQL 使用哪个约束名称。

在syntax

[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)

约束名称应该是 symbol 或者,如果没有给出,则自动创建:

如果给出了 CONSTRAINT 符号子句,则符号值(如果使用)在数据库中必须是唯一的。重复的符号会导致类似的错误:ERROR 1022 (2300): Can't write;表“#sql-464_1”中的重复键。如果没有给出子句,或者 CONSTRAINT 关键字后面没有包含符号,则会自动创建约束名称。

这通常会像这样工作:

使用符号 否则自动创建名称(格式为 tablename_ibfk_id

如果您禁用FOREIGN_KEY_CHECKS,对于ALTER TABLE,而不是对于CREATE TABLE,它将额外使用index_name

使用 index_name 如果没有给出 index_name,则使用 symbol 否则自动创建名称(格式为 tablename_ibfk_id

因此,虽然 index_name 通常只需要在每个表中都是唯一的,但在这里,您的两个 ALTER 语句中的常见 index_name person_id 会引起麻烦,因为 MySQL 试图创建两个具有相同(错误)名称的约束。

作为一种解决方法,在你的情况下,你可以从你的 alter 语句中删除 index_name person_id,因为如果一切正常,索引应该得到 给出的名称符号

如果子表上已经有明确定义的索引可以支持外键,则忽略 index_name 值。否则,MySQL 会隐式创建一个根据以下规则命名的外键索引:

如果已定义,则使用 CONSTRAINT 符号值。否则,使用 FOREIGN KEY index_name 值。

如果既没有定义 CONSTRAINT 符号也没有定义 FOREIGN KEY index_name,则使用引用外键列的名称生成外键索引名称。

如果您想显式命名索引,但使用默认约束名称,您可以在添加外键之前添加索引,例如使用

ALTER TABLE phppos_customers ADD INDEX person_id (person_id);
ALTER TABLE phppos_customers ADD CONSTRAINT FOREIGN KEY (person_id) REFERENCES ...

MySQL 8 表现出稍微不同的行为(当 FOREIGN_KEY_CHECKS 被禁用且仅适用于 ALTER TABLE):它也错误地使用了 index_name,但前提是没有 symbol > 给出 - 在你的情况下它会起作用,因为你设置了 symbol

【讨论】:

感谢您的出色回答。我遇到了同样的问题,我通过添加约束名称来修复它。当您不提供约束名称时,MySQL 似乎有问题。

以上是关于MYSQL 错误 1823 当 SET FOREIGN_KEY_CHECKS=1的主要内容,如果未能解决你的问题,请参考以下文章

无法安装旧的 mysql2 gem

MySQL读取Binlog日志常见的3种错误

MySQL 触发语法错误

详细信息使用自定义模型通过LINQ查看相关数据

bzoj1823满汉全席

mysql SET FOREIGN_KEY_CHECKS=0 不能从命令行或 shell 脚本工作