Как применять ограничения и использовать НЕТ правил действий означает БЕЗ ДЕЙСТВИЙ - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь уточнить правильное использование ограничений внешнего ключа и постоянно нажимаю пробел, когда дело доходит до «УДАЛИТЬ» «НЕТ ДЕЙСТВИЯ» Я буду придерживаться общих принципов, поскольку это очень просто, не вдаваясь в детали.

У меня есть родительская таблица, в которой есть 5 дочерних таблиц. данные во всех таблицах (это не новая сборка БД). Я хочу установить все логично, чтобы соответствовать потребностям моего клиента, и я бы ожидал! Существует связь один-много со всеми родительскими и дочерними таблицами следовательно: может быть ноль или много записей, относящихся к родительской таблице первичный ключ Там никогда не может быть дочерняя запись, которая не относятся к родительским записям (я уже проверил, чтобы убедиться, что это так).

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

  • Если дочерняя запись (Fk) ОБНОВЛЕНА, обновите родительский (PK) до того же.
  • Если дочерняя запись (Fk) удалена, разрешите удаление дочерней записи, но не предпринимайте никаких действий с родительской (Pk) записью (супер важно!)
  • Если родительская запись удалена, удалите ее и все связанные дочерние записи во ВСЕХ дочерних таблицах

Однако я читаю потоки в документах SO и MySQL, в которых говорится, что «НЕТ ДЕЙСТВИЯ» - это то же самое, что «ОГРАНИЧЕНИЕ», что может вызвать проблемы, если я не смогу удалить дочерние записи. В своем PHP-коде я использую в основном операторы INSERT INTO и операторы ON DUPLICATE KEY UPDATE. Я склонен полностью удалить ограничения внешнего ключа с уровня БД и просто реализовать то, что я хочу достичь, как я делаю в моем PHP / PDO. Я на самом деле использую ограничения по внешнему ключу, потому что думаю, что должен, но на самом деле не понимаю, так как обновление первичного ключа никогда не должно происходить.

Какой лучший способ сделать это. Что является хорошим вариантом использования «НЕТ ДЕЙСТВИЙ», если оно фактически предотвращает, а не защищает.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

@ Билл Карвин и авторы этого вопроса. С тех пор я понял, что установка БД была неправильной, поэтому мне нужно было удалить ограничения FK, чтобы работать с ней. БД была перенесена из MS Access, и, как и некоторые различия в типах данных, проверки ограничений внешнего ключа были отключены, когда импорт БД в mySQL без этого импорта был невозможен. Уже одно это указывало на проблемы с настройкой правил ограничений в MS Access.

Работа с экспортированной базой данных в MySQL теперь выявила много потерянных записей и проиндексированных полей, которые уже нарушили ограничения FK, будучи нулевыми или пустыми! - при исправлении этих ошибок и правильной нормализации БД / Таблиц были сделаны предложения здесь.

Спасибо за ваш вклад.

0 голосов
/ 31 октября 2018

«НЕТ ДЕЙСТВИЙ» - это то же самое, что и «ОГРАНИЧЕНИЕ», что может вызвать проблемы, если я не смогу удалить дочерние записи.

Это не то, что означает это условие. Он не мешает вам удалять дочерние записи, он предотвращает удаление родительских записей тогда и только тогда, когда существуют дочерние записи, которые зависят от родительской записи.

Пример:

Таблица Orders имеет отношение один-ко-многим с LineItems, а внешний ключ в LineItems имеет параметр restrict.

CREATE TABLE Orders (
  order_id INT NOT NULL,
  PRIMARY KEY (order_id)
);

CREATE TABLE LineItems (
  lineitem_id INT NOT NULL,
  order_id INT NOT NULL,
  PRIMARY KEY (lineitem_id),
  FOREIGN KEY (order_id) REFERENCES Orders (order_id) ON DELETE RESTRICT
);

Создать тестовые данные:

mysql> INSERT INTO Orders SET order_id = 123;
Query OK, 1 row affected (0.02 sec)

mysql> INSERT INTO LineItems SET lineitem_id = 1, order_id = 123;
Query OK, 1 row affected (0.02 sec)

Мы не можем удалить запись Orders, потому что в зависимости от нее есть LineItem:

mysql> DELETE FROM Orders WHERE order_id = 123;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`lineitems`, CONSTRAINT `lineitems_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `Orders` (`order_id`))

Но мы можем удалить запись LineItems в любое время:

mysql> DELETE FROM LineItems WHERE order_id = 123;
Query OK, 1 row affected (0.01 sec)

Теперь, когда нет записей LineItems, ссылающихся на запись Orders, мы также можем удалить эту запись:

mysql> DELETE FROM Orders WHERE order_id = 123;
Query OK, 1 row affected (0.01 sec)
...