Удаление с помощью циклических внешних ключей - PullRequest
1 голос
/ 14 ноября 2011

У меня есть две сущности, каждая из которых ссылается друг на друга: Page сущность, которая имеет ссылку на defaultUrl, и Url сущность, которая имеет ссылку на page.

Этоциклический и поэтому, как только я добавляю страницу и URL, которые ссылаются друг на друга, я не могу удалить их.

Я вижу два способа исправить это, но я не уверен в способе «Доктрины» сделать это.

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

Я не могне могу понять, как это сделать ... ты знаешь ??

Спасибо!

Ответы [ 2 ]

2 голосов
/ 14 ноября 2011

Вот способ Доктрины установить это.Как было упомянуто ранее, вам нужно установить хотя бы один из внешних ключей для обнуляемости.

Также рассмотрите возможность установки каскадов onDelete на SET NULL.Это сделает процесс удаления еще проще - вам не придется обновлять ключ до NULL перед удалением записи.

Ваш schema.yml может выглядеть так:

Url:
  columns:
    page_id: { type: integer, notnull: true }
  relations:
    Page: { local: page_id, foreign: id }

Page:
  columns:
    default_url_id: { type: integer, notnull: false }  # ALLOWS NULL foreign key here
  relations:
    DefaultUrl: { class: Url, local: default_url_id, foreign: id, onDelete: SET NULL }
1 голос
/ 14 ноября 2011

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

Это позволяет прерывать цикл.

Простейший случай (синтаксис SQL, но принцип sampe)применяется):

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NOT NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)

Может быть разорван цикл следующим образом:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NOT NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
)

или следующим образом:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)

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

РЕДАКТИРОВАТЬ: я обнаружил, что, когда вы задаете вопрос эксперту по книге, вы получаете ответ, например отключение внешнего ключа во время удаления.Это неправильно по двум причинам.Во-первых, обычные транзакционные операции не должны изменять определения схемы.Во-вторых, остальная часть кода ожидает присутствия внешнего ключа и поэтому не обрабатывает его в коде приложения;однако модификации схемы имеют неприятную привычку перетекать через транзакции или блокировать целые таблицы.

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