外键不能像我预期的那样工作

yas*_*sar 5 innodb foreign-key constraint

这是我的桌子;

CREATE TABLE `borclular` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tc` char(11) COLLATE utf8_turkish_ci NOT NULL,
  `borclu` varchar(255) COLLATE utf8_turkish_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `tc` (`tc`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci

 CREATE TABLE `dosyalar` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `kurum_id` int(11) NOT NULL,
  `borclu_id` int(11) NOT NULL,
  `hizmetno` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `kurum_id_index` (`kurum_id`),
  KEY `borclu_id_index` (`borclu_id`),
  CONSTRAINT `borclu_id_foreign` FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`),
  CONSTRAINT `kurum_id_foreign` FOREIGN KEY (`kurum_id`) REFERENCES `kurumlar` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci
Run Code Online (Sandbox Code Playgroud)

当我从 borculular 中删除一行时,我希望 dosyalar 中的相关行也被删除。但是,当我尝试从 borclular 中删除一行时,出现以下错误;

Cannot delete or update a parent row: a foreign key constraint fails (`iletisim`.`dosyalar`, CONSTRAINT `borclu_id_foreign` FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`))
Run Code Online (Sandbox Code Playgroud)

Dav*_*ett 8

正如布朗斯通先生所指出的(这只是一个评论,但结果太长了)如果您将密钥定义为ON DELETE CASCADE.

我会非常小心ON DELETE CASCADE,事实上我几乎从不使用它,并且通常不推荐它。这也适用于根据行被删除而采取行动的触发器。如果一个天真的程序员后来UPSERT通过执行 aDELETE后跟 an来实现父行INSERT(这是我的经验中非常常见的模式),那么子数据将全部丢失,因为删除是级联的,级联删除的行显然不是由随后的插入替换。

此外,如果您的 UI 由于错误而允许用户尝试删除他们真正不应该删除的内容,因为其他地方的行依赖于它,您(或用户)会收到错误,而不是数据库默默地删除错误的内容及其子项.

有时没有打开级联选项意味着您需要在数据访问或业务逻辑层中进行额外的工作以在父对象之前手动删除子对象,但我认为这通常是一个很小的代价。

警告:有些人认为我的立场是一种不必要的偏执。你的旅费可能会改变。


Wor*_*DBA 7

您需要指定您希望删除操作像这样级联:

CONSTRAINT `borclu_id_foreign` 
FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`) ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

如果您未指定ON DELETEON UPDATE则默认为RESTRICT,来自文档:

对于未指定的 ON DELETE 或 ON UPDATE,默认操作始终为 RESTRICT。

可以在这里找到:

https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html