【问题标题】:MySQL - Error 1823: Failed to add the foreign key constraint to system tablesMySQL - 错误 1823:无法将外键约束添加到系统表
【发布时间】:2018-11-11 21:17:01
【问题描述】:

我正在更新数据库以更正更新和删除时的外键行为。然而,特别是在一张桌子上,这出乎意料地困难。

在大多数桌子上,我一直在执行以下操作,没有任何问题:

  1. 删除外键约束
  2. 删除对应的索引
  3. 添加新的更新外键

然而,一张桌子造成了一些我不太理解的麻烦。尝试执行上述过程会返回以下错误(我已将数据库名称编辑为 db_name):

SQLSTATE[HY000]: General error: 1025 Error on rename of 
'./<db_name>/#sql-5e1_1c5' to './<db_name>/doctors' 
(errno: 150 - Foreign key constraint is incorrectly formed)
(SQL: alter table `doctors` drop index `doctors_id_unique`)

表格相关部分如下,初步

  UNIQUE KEY `doctors_id_unique` (`id`),
  UNIQUE KEY `doctors_code_unique` (`code`),
  KEY `doctors_updated_by_foreign` (`updated_by`),
  CONSTRAINT `doctors_id_foreign` FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
  CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我想把id改成主键外键,所以我做了以下操作:

ALTER TABLE doctors DROP FOREIGN KEY doctors_id_foreign;
ALTER TABLE doctors DROP INDEX doctors_code_unique;
ALTER TABLE doctors DROP INDEX doctors_id_unique;

但是,在第三条语句中,我收到以下错误:

Error on rename of './<db_name>/#sql-5e1_2' to './<db_name>/doctors' 
(errno: 150 - Foreign key constraint is incorrectly formed)

我不知道如何解决这个问题。我尝试首先删除 updated_by 约束和键以及 code 唯一键,但它不会改变任何东西。我尝试禁用外键检查,但没有雪茄。

我尝试更改用于测试的 SQL 转储。将其更改为以下内容使其可以按我的预期工作,至少很明显:

  PRIMARY KEY (`id`),
  UNIQUE KEY `doctors_code_unique` (`code`),
  KEY `doctors_updated_by_foreign` (`updated_by`),
  CONSTRAINT `doctors_id_foreign` FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

但是,我宁愿以编程方式更新表,以便更轻松可靠地进行迁移。所以我尝试了一种不同的方法,只是重命名表,将它复制到一个新的,然后在其中添加键:

SET FOREIGN_KEY_CHECKS=0;
RENAME TABLE `doctors` TO `old_doctors`;
CREATE TABLE `doctors` SELECT * FROM `old_doctors`;
ALTER TABLE `doctors` ADD PRIMARY KEY (`id`);
ALTER TABLE `doctors` ADD UNIQUE INDEX `doctors_code_unique` (`code`);
ALTER TABLE `doctors` ADD CONSTRAINT `doctors_id_foreign` FOREIGN KEY `doctors_id_foreign` (`id`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE `doctors` ADD CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY `doctors_updated_by_foreign` (`updated_by`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE SET NULL;
SET FOREIGN_KEY_CHECKS=1;

现在我收到以下错误:

SQLSTATE[HY000]: General error: 1823 Failed to add the foreign key constraint
'<db_name>/doctors_id_foreign' to system tables (SQL: ALTER TABLE `doctors`
ADD CONSTRAINT `doctors_id_foreign` FOREIGN KEY `doctors_id_foreign` (`id`) 
REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE)

所以我无法让它工作,而且这两个错误似乎都不常见:我找不到任何关于如何处理它们的好信息。

这太费时了,我可能会关闭服务器,转储数据库,手动修复转储并将修复的转储导入回来;但是,我真的很想知道这是一些错误还是我只是错过了一些东西。这很有可能,因为我几乎不是一个经验丰富的程序员。

对于上下文:这一切都在 Laravel (5.7.13) 项目上,但错误发生在使用 Laravel 迁移(使用模式和蓝图)和直接通过 SQL 控制台时。 MySQL 版本 5.7.22。

tl;dr:我只是无法更改表的外键在更新/删除时的行为,尽管在同一数据库上的其他各种表上都成功地这样做了。我尝试了两种截然不同的方法来修复它,并且都返回(不同的)错误,我在任何地方都找不到解决方案。是错误还是我遗漏了什么?

【问题讨论】:

  • 请在更改外键之前提供表状态的 SQL 转储。是否有其他表在其外键中引用此表?
  • @JonasStaudenmeir 问题在于引用此表 ID 的其他表:我将迁移更改为 1) 删除引用 doctors.id 的外键; 2)更新doctors表; 3)恢复引用doctors.id的外键,终于成功了。您可以将其发布为答案,以便我标记它吗?谢谢!

标签: mysql laravel


【解决方案1】:

确保没有其他表在其外键中引用 doctors.id 列。

如果是,请在删除 doctors_id_unique 索引之前删除这些外键。

doctors.id设为主键后恢复外键。

【讨论】:

  • 解决了! IMO 错误消息可能更清楚,但我应该知道问题可能出在其他表的外键引用的列上。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 2018-04-28
相关资源
最近更新 更多