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 通常只需要在每个表中都是唯一的,但在这里,您的两个 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的主要内容,如果未能解决你的问题,请参考以下文章