SQL Удалить с отношением 1 к 1 - PullRequest
2 голосов
/ 19 декабря 2011

Моя база данных - MySQL с управлением внешним ключом. Имеет 2 таблицы:

Table1 :
|id|foreignKeyToTable2|data...|

Table2 : 
|id|foreignKeyToTable1|data...|

Я хочу удалить пару этих строк, но когда я удаляю одну из них, у меня появляется значительная ошибка внешнего ключа.

Как я могу удалить пару строк за один раз?

Я вынужден отключить проверку внешних ключей?

Редактировать: проблема с каскадом удаления

Мне нужны оба ключа, потому что на самом деле есть 2 отношения. Давайте будем практичнее:

  • таблица 1 представляет собой «выпадающий список» со значением по умолчанию.
  • таблица 2 имеет все возможные значения для каждого DDL в таблице 1.

Таблицы:

DDL
|id|name|defaultValue (FK delete cascade)|
Value
|id|name|DDLiD (FK)|

После ваших ответов я добавил DELETE CASCADE в таблицу DDL. Но у меня все еще есть ошибка FK.

Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не выполняется (Значение, CONSTRAINT fk_Value_DDL FOREIGN KEY (DDL) ССЫЛКИ DDL (id) ВКЛ

Я не хочу добавлять каскад удаления в таблицу значений, потому что хочу иметь возможность удалить значение.

Ответы [ 5 ]

3 голосов
/ 19 декабря 2011

У вас есть две опции:

  1. Изменить определение внешнего ключа, чтобы также удалить строки, на которые имеются ссылки.Это можно сделать с помощью ON DELETE CASCADE.
  2. Используйте транзакцию вокруг двух операторов удаления.

Второй вариант - мой предпочтительный, поскольку пользователь базы данных информируется об использовании в другомtable, а затем может принять решение об использовании транзакции для удаления данных из обеих строк.

Кроме того, один сценарий использования отношения 1: 1 должен разрешать разные разрешения для обеих таблиц.При использовании каскада удаления я не знаю, проверяются ли они.

РЕДАКТИРОВАТЬ

После того, как мне было указано, что MySQL обрабатывает проверку внешнего ключа не так, как указано в SQLСтандарты, мой второй вариант изменен на:

2.Поскольку MySQL не поддерживает отложенную проверку ограничений внешнего ключа при использовании транзакций (это отклонение от стандартов SQL), необходимо отключить проверки внешнего ключа для операторов удаления:

    SET foreign_key_checks = 0;
    DELETE ...;
    SET foreign_key_checks = 1;
2 голосов
/ 19 декабря 2011

Вам необходимо установить внешний ключ в каскадный режим:

CREATE TABLE table1 (
  fields....
  FOREIGN KEY fk_name(fk_to_table2) REFERENCES table2.id  
  ON DELETE CASCADE ON UPDATE CASCADE   <<--- Change this.

Если вы измените раскладку таблицы следующим образом, MySQL не заблокирует, а распространит удаление.

Примечаниечто если у вас есть отношение 1 к 1, у вас нет отдельного поля внешнего ключа, но ваш первичный ключ связан с другим первичным ключом, например так:

CREATE TABLE t1 (
  id UNSIGNED INTEGER AUTO_INCREMENT PRIMARY KEY,
  otherfields....,
) ENGINE = InnoDB;  <<-- no foreign key in T1, because t1 is the master.


CREATE TABLE t2 (
  id UNSIGNED INTEGER AUTO_INCREMENT PRIMARY KEY,
  otherfields....,
  FOREIGN KEY fk_t1_id(id) REFERENCES t1(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;  <<-- t2 follows t1.

Теперь вы вводите 1-1 отношение, а не 1-н.

Обратите внимание, что значение NO ACTION совпадает с RESTRICT: http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html

НЕТ ДЕЙСТВИЯ: ключевое слово из стандартного SQL.В MySQL эквивалентен RESTRICT.InnoDB отклоняет операцию удаления или обновления для родительской таблицы, если в указанной таблице есть значение связанного внешнего ключа.Некоторые системы баз данных имеют отложенные проверки, и NO ACTION является отложенной проверкой.В MySQL ограничения внешнего ключа проверяются немедленно, поэтому NO ACTION - это то же самое, что и RESTRICT.

1 голос
/ 19 декабря 2011

Использование каскадного удаления / обновления должно обрабатывать все необходимое.

У меня есть альтернативное предложение, которое является скорее архитектурным растворителем / решимостью.

  • По замыслу: вместо удаления данных всегда отключайте их
  • Вы можете сохранить столбец: Status | BIT | Default(1)
  • Этот столбец может присутствовать или не присутствовать во вторичной таблице
  • По коду-дизайн все, что вам нужно обрабатывать, это когда вы получаете (все запросы SELECT) вторичные данные, всегда ставьте условие: PrimaryTable.Status = 1 при соединении с первичной таблицей
  • Это исключает необходимость применения ограниченийпо дизайну первичного стола
0 голосов
/ 19 декабря 2011

Решение, которое я нашел, состоит в том, чтобы удалить один из внешних ключей и управлять им с помощью приложения. Таблицы сейчас:

DDL
|id|name|defaultValue|
Value
|id|name|DDLiD (FK)|

defaultValue - это идентификатор таблицы Value, но не внешний ключ ...

Когда я хочу удалить, сначала я удаляю значения, затем я удаляю DDL.

Спасибо всем.

Nicolas.

0 голосов
/ 19 декабря 2011

Используйте on delete cascade при создании таблицы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...