设置外键检查=1时出现MYSQL错误1823
我有一个奇怪的错误,当执行FOREIGN\u KEY\u CHECKS=0和2个查询时(除了FOREIGN\u CHECK\u检查外,这两种情况都是相同的) 该错误导致错误1823(HY000):未能添加外键约束…(下面是完整错误) 如果我使用SET-FOREIGN\u-KEY\u-CHECKS=1运行查询,它将按预期工作。(这几乎像是说,关闭外键检查应该让事情过去,但不应该) 这是mysql中的错误还是我不理解?我找不到关于这个mysql错误代码的很多信息 MYSQL VERISON: 5.6.33 错误(上次查询): 成功:设置外键检查=1时出现MYSQL错误1823,mysql,Mysql,我有一个奇怪的错误,当执行FOREIGN\u KEY\u CHECKS=0和2个查询时(除了FOREIGN\u CHECK\u检查外,这两种情况都是相同的) 该错误导致错误1823(HY000):未能添加外键约束…(下面是完整错误) 如果我使用SET-FOREIGN\u-KEY\u-CHECKS=1运行查询,它将按预期工作。(这几乎像是说,关闭外键检查应该让事情过去,但不应该) 这是mysql中的错误还是我不理解?我找不到关于这个mysql错误代码的很多信息 MYSQL VERISON: 5.6
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)
是的,这似乎是一个bug。我可以在MySQL 5.6+(和MySQL 8类似)中验证它,而5.5不受影响。这里的问题是MySQL使用哪个约束名称 在 约束名称应为symbol或(如果未给出)自动创建: 如果给定了CONSTRAINT symbol子句,则符号值(如果使用)在数据库中必须是唯一的。重复的符号将导致类似以下错误:错误1022(2300):无法写入;表“#sql-464_1”中存在重复键。如果未给出子句,或约束关键字后未包含符号,则会自动创建约束的名称 这通常是这样工作的:
- 使用符号
- 否则自动创建名称(以tablename\u ibfk\u id的形式)
外键检查
,对于更改表
,而不是创建表
,它将另外使用索引名称:
- 使用索引名称
- 如果未给出索引名称,则使用符号
- 否则自动创建名称(以tablename\u ibfk\u id的形式)
ALTER
语句中的公共索引名person\u id
将导致问题,因为MySQL试图使用相同(错误)的名称创建两个约束
作为一种解决方法,在您的情况下,您可以从alter语句中删除索引_nameperson\u id
,因为如果一切正常,索引无论如何都应该使用符号给出的名称:
如果子表上已经有一个显式定义的索引可以支持外键,则忽略index_name值。否则,MySQL将隐式创建一个根据以下规则命名的外键索引:
- 如果已定义,则使用约束符号值。否则,将使用外键索引名称值
- 如果未定义约束符号或外键索引名称,则使用引用外键列的名称生成外键索引名称
ALTER TABLE phppos_customers ADD INDEX person_id (person_id);
ALTER TABLE phppos_customers ADD CONSTRAINT FOREIGN KEY (person_id) REFERENCES ...
MySQL 8显示了稍微不同的行为(当
外键检查
被禁用并且仅用于更改表
):它也错误地使用了索引名称,但只有在没有给出任何符号的情况下才使用。在您的情况下,这是可行的,因为您设置了符号。谢谢您的回答。我也遇到了同样的问题,我通过添加约束名称来修复它。当您不提供约束名称时,MySQL似乎有问题。
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
ALTER TABLE phppos_customers ADD INDEX person_id (person_id);
ALTER TABLE phppos_customers ADD CONSTRAINT FOREIGN KEY (person_id) REFERENCES ...