Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 删除具有递归外键约束的记录_Mysql_Foreign Keys_Constraints - Fatal编程技术网

Mysql 删除具有递归外键约束的记录

Mysql 删除具有递归外键约束的记录,mysql,foreign-keys,constraints,Mysql,Foreign Keys,Constraints,从一个表中删除记录的最佳方法是什么?该表的外键指向另一个表,而另一个表的外键指向另一个表 例如,我有以下表格帐户有一个或多个网络,帐户必须有一个默认网络 CREATE TABLE IF NOT EXISTS accounts ( id INT NOT NULL, networksId INT NOT NULL, PRIMARY KEY (id), INDEX fk_accounts_networks1_idx (networksId ASC), CONSTRAINT fk_a

从一个表中删除记录的最佳方法是什么?该表的外键指向另一个表,而另一个表的外键指向另一个表

例如,我有以下表格<代码>帐户有一个或多个网络,
帐户
必须有一个默认网络

CREATE TABLE IF NOT EXISTS accounts (
  id INT NOT NULL,
  networksId INT NOT NULL,
  PRIMARY KEY (id),
  INDEX fk_accounts_networks1_idx (networksId ASC),
  CONSTRAINT fk_accounts_networks1
    FOREIGN KEY (networksId)
    REFERENCES networks (id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS networks (
  id INT NOT NULL AUTO_INCREMENT,
  accountsId INT NOT NULL,
  PRIMARY KEY (id),
  INDEX fk_sites_accounts1_idx (accountsId ASC),
  CONSTRAINT fk_sites_accounts1
    FOREIGN KEY (accountsId)
    REFERENCES accounts (id)
    ON DELETE CASCADE
    ON UPDATE NO ACTION)
ENGINE = InnoDB;
尽管我对网络FK到帐户进行了级联删除,但我尝试显式删除网络,希望绕过外键约束,但没有成功

DELETE a, n FROM accounts a INNER JOIN networks n ON n.accountsId=a.id WHERE a.id=123;
我唯一的解决方案是下面这样的吗

SET FOREIGN_KEY_CHECKS=0;
DELETE FROM networks WHERE accountsId=123;
SET FOREIGN_KEY_CHECKS=1;
DELETE FROM accounts WHERE id=123;

这两个表之间有一个约束相互依赖关系。这不是一个好的设计,因为它会使DDL和DML操作比通常需要的更复杂

除了暂时禁用外键外,执行成功删除的唯一可能解决方案是使其中一个引用字段可为NULL,以便在删除前将其设置为NULL,从而中断关系。ON DELETE级联将负责删除另一个表中的相关记录

将其中一个引用字段设置为空:

ALTER TABLE networks MODIFY accountsId INT NULL;
删除:

UPDATE network SET accountsId = NULL WHERE id = ?;
DELETE FROM network WHERE id = ?;
-- the corresponding record in table accounts gets automatically deleted.

谢谢GMB。另一个选择是修改表,但我认为这样做不是一个好的解决方案。我没有这么说,但是
account.networksId
表示帐户的默认网络。我认为,这两个约束正确地模拟了这种关系。为什么你觉得这是一个糟糕的设计(除了使DDL和DML运算符比通常需要的更复杂)?@user1032531:我理解你关于两个约束如何建模关系的观点。我说这是糟糕的设计,只是因为大多数RDBMS都不能很好地处理这个用例。。。