Удалить записи с рекурсивными ограничениями внешнего ключа - PullRequest
0 голосов
/ 30 декабря 2018

Каков наилучший подход для удаления записей из таблицы, у которой есть внешний ключ к другой таблице, а у другой таблицы есть внешний ключ к ней?

Например, у меня есть следующие таблицы.accounts имеет одну или несколько сетей, а accounts должна иметь одну сеть по умолчанию.

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;

Несмотря на то, что у меня есть CASCADE DELETE в сетях 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;

1 Ответ

0 голосов
/ 31 декабря 2018

У вас есть взаимозависимость ограничений между обеими таблицами.Это не очень хороший дизайн, потому что он делает операции DDL и DML более сложными, чем обычно необходимо.

Помимо временного отключения внешнего ключа, единственное возможное решение для успешного выполнения DELETE - это сделать одно из следующих действий:ссылающиеся поля обнуляются, так что вы можете разорвать отношение, установив его в NULL перед удалением.ON DELETE CASCADE позаботится о том, чтобы удалить соответствующую запись в другой таблице.

Сделать одно из ссылочных полей обнуляемым:

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...