首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有外键约束的删除顺序,

具有外键约束的删除顺序,
EN

Stack Overflow用户
提问于 2018-10-19 02:38:37
回答 1查看 776关注 0票数 2

我有一个有三个表和外键'On Delete‘约束的模式,如下所示:

代码语言:javascript
复制
               |      ->         FK (cascade)        ->       |
Organisation   |                                              |  Users
               | - FK (cascade) Categories -> FK(restrict) -> |

如果我删除一个组织,我想删除用户和与它相关的类别,但如果用户引用它,我不能允许删除一个类别,除非整个组织被删除。

目前,如果我删除一个组织,类别删除失败,如果有用户引用它。这似乎表明MySQl正在处理用户表之前的类别表上的外键约束。

如果在类别之前清除了user表中的用户,这将不会是一个问题。

有没有办法告诉MySQl处理这些FK约束的顺序是什么,以便按照指定的顺序清除表?

注意:我可以添加一些代码来显式清除用户表,但是这在代码的设计中是很复杂的,所以我还不想去那里。

还要注意的是,所需的安全性限制了我对模式所能做的事情,因此更改FK约束或禁用对它们的检查并不是一个真正的选择。我可以换个安检单换一次。除非没有其他办法,否则我不想永久放松安全措施。最好像上面那样编写额外的代码。

下面是表的Create语句,编辑这些语句以删除不相关的字段。

代码语言:javascript
复制
CREATE TABLE `organisation` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orgGUID` varchar(36) NOT NULL,
  `archivedFlag` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `orgName` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  UNIQUE KEY `org_guid_UNIQUE` (`orgGUID`)
) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8;

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userGUID` varchar(36) NOT NULL,
  `name` varchar(45) NOT NULL,
  `orgGUID` varchar(36) NOT NULL,
  `userType` smallint(6) DEFAULT NULL,
  `PwHash` varchar(255) DEFAULT NULL,
  `ethnicityGUID` varchar(36) DEFAULT NULL ,
  `genderGUID` varchar(36) DEFAULT NULL ,
  `yearGroupGUID` varchar(36) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  UNIQUE KEY `userGUID_UNIQUE` (`userGUID`),
  KEY `fk_user_org_idx` (`orgGUID`),
  KEY `fk_ethnicity_category_idx` (`ethnicityGUID`),
  KEY `fk_gender_category_idx` (`genderGUID`),
  CONSTRAINT `fk_ethnicity_category` FOREIGN KEY (`ethnicityGUID`) REFERENCES `categories` (`id`) ON UPDATE NO ACTION,
  CONSTRAINT `fk_gender_category` FOREIGN KEY (`genderGUID`) REFERENCES `categories` (`id`) ON UPDATE NO ACTION,
  CONSTRAINT `fk_user_org` FOREIGN KEY (`orgGUID`) REFERENCES `organisation` (`orgGUID`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=162 DEFAULT CHARSET=utf8;

CREATE TABLE `categories` (
  `id` varchar(36) NOT NULL,
  `orgGUID` varchar(36) NOT NULL,
  `categoryType` varchar(20) NOT NULL,
  `category` varchar(45) NOT NULL,
  `priority` int(11) NOT NULL,
  `analysisCode` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  KEY `fk_category_org_idx` (`orgGUID`),
  CONSTRAINT `fk_category_org` FOREIGN KEY (`orgGUID`) REFERENCES `organisation` (`orgGUID`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-19 09:58:15

根据官方说法,您无法控制级联操作的顺序。然而,你可能会滥用一些无证件的行为:

  • 对于MySQL 5.5,外键是按照创建的顺序执行的,所以删除和重新创建fk_category_org-constraint应该有效
  • 对于MySQL 5.6+,外键按名称的词法顺序执行,因此将fk_category_org重命名为例如,fk_z_category_org应该可以工作

这是没有记录的,可以随时改变(并且可能受到其他因素的影响)。

尽管如此,正确的方法(以及其他对on cascade来说太复杂的事情)将是在organisation-table上添加一个before delete-触发器,“手动”先删除用户,然后删除类别。before delete-triggers是在on cascade之前执行的(因此您可以决定是否保留这些文件,尽管这可能会产生误导)。

还不完全清楚这是否是您的有意行为,但目前,用户可以有一个属于组织1的类别,而他被分配到组织2。删除组织1仍然会失败。看起来,这似乎是您希望通过您的设计来防止的,但是如果您希望删除在这种情况下也能工作,您需要使用触发器才能将其合并(或在您的应用程序中手动删除它),除非您还在类别表中级联,否则级联将无法工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52885132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档