Ограничение внешнего ключа может вызвать циклы или несколько каскадных путей?

Давайте рассмотрим довольно обычный пример этого процесса. Мы хотим зарегистрировать нового пользователя, а также создали модель профиля, в которой мы хотим, чтобы профиль пользователя сохранялся только при сохранении действительной информации о пользователе.

Мы можем создать нового пользователя в админке Django и использовать метод saved_model в ModelAdmin, чтобы сохранить другие части формы в модели Profile. Это «нормальный» способ сделать это. Но, используя этот способ, вы можете получить доступ к пользователю и профилю только из панели администратора Django. Форма «Регистрация пользователя» за пределами Администратора Django не будет работать , поскольку для доступа к элементам управления Администратора Django необходимо будет зарегистрироваться.

Но с помощью сигнала post_save можно создать и обновить нового пользователя и профиль независимо от того, используете ли вы панель администратора Django или пользовательскую форму, которая сохраняется в моделях User и Profile.

Поэтому использование сигналов является наиболее гибким, но теперь вам нужно убедиться, что у вас есть способ проверки информации, поступающей из пользовательской формы.

171
задан Ricardo Altamirano 9 July 2012 в 20:41
поделиться

4 ответа

SQL Server выполняет простой подсчет каскадных путей, и вместо того, чтобы пытаться выяснить, существуют ли на самом деле какие-либо циклы, он предполагает худшее и отказывается создавать ссылочные действия (CASCADE): вы можете и все равно должны создавать ограничения без ссылочных действий. Если вы не можете изменить свой дизайн (или это может поставить под угрозу), вам следует подумать об использовании триггеров в крайнем случае.

FWIW, разрешающий каскадные пути, является сложной проблемой. Другие продукты SQL просто проигнорируют проблему и позволят вам создавать циклы, и в этом случае будет гонка за тем, какое значение будет перезаписано последним, вероятно, по незнанию дизайнера (например, ACE / Jet делает это). Я понимаю, что некоторые продукты SQL пытаются разрешить простые случаи. Факт остается фактом, SQL Server даже не пытается, играет очень безопасно, запрещая более одного пути, и, по крайней мере, он вам об этом говорит.

Сама Microsoft советует использовать триггеры вместо ограничений FK.

172
ответ дан 23 November 2019 в 20:44
поделиться

Судя по звукам, у вас есть действие OnDelete / OnUpdate на одном из ваших существующих внешних ключей, которое изменит вашу таблицу кодов.

Таким образом, создав этот внешний ключ, вы должны создавать циклическую проблему,

Например, обновление сотрудников, вызывает изменение кодов действием при обновлении, вызывает изменение сотрудников действием при обновлении ... и т. д.

Если вы публикуете определения таблиц для обе таблицы и ваши определения внешнего ключа / ограничений, мы сможем сказать вам, в чем проблема ...

3
ответ дан 23 November 2019 в 20:44
поделиться

Я бы указал из этого (функционально) существует БОЛЬШАЯ разница между циклами и / или несколькими путями в СХЕМЕ и ДАННЫХ. Хотя циклы и, возможно, многолучевость в ДАННЫХ, безусловно, могут усложнить обработку и вызвать проблемы с производительностью (стоимость «правильной» обработки), стоимость этих характеристик в схеме должна быть близка к нулю.

Поскольку наиболее очевидные циклы в РБД происходят в иерархических структурах (организационная диаграмма, часть, подраздел и т. Д.), К сожалению, SQL Server предполагает худшее; т.е. цикл схемы == цикл данных. Фактически, если вы используете ограничения RI, вы не можете построить цикл в данных!

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

Конечно, если бы SQL Server позволял циклы, он все равно имел бы глубину 32, но этого, вероятно, достаточно для большинства случаев. (Жаль, что это не настройка базы данных!)

Триггеры «Вместо удаления» тоже не работают. При втором посещении таблицы триггер игнорируется. Итак, если вы действительно хотите смоделировать каскад, вам придется использовать хранимые процедуры при наличии циклов. Однако триггер вместо удаления будет работать для случаев многолучевого распространения.

Celko предлагает «лучший» способ представления иерархий, который не вводит циклы, но есть компромиссы.

12
ответ дан 23 November 2019 в 20:44
поделиться

Типичная ситуация с несколькими путями каскадирования будет такой: Главная таблица с двумя деталями, допустим, "Master" и "Detail1" и "Detail2". Обе детали каскадно удаляются. До сих пор никаких проблем. Но что если обе детали имеют связь "один-ко-многим" с какой-то другой таблицей (скажем, "SomeOtherTable"). SomeOtherTable имеет Detail1ID-столбец И Detail2ID-столбец.

Master { ID, masterfields }

Detail1 { ID, MasterID, detail1fields }

Detail2 { ID, MasterID, detail2fields }

SomeOtherTable {ID, Detail1ID, Detail2ID, someothertablefields }

Другими словами: некоторые записи в SomeOtherTable связаны с Detail1-записями, а некоторые записи в SomeOtherTable связаны с Detail2-записями. Даже если гарантируется, что записи SomeOtherTable никогда не принадлежат обеим деталям, теперь невозможно сделать каскадное удаление записей SomeOhterTable для обеих деталей, потому что существует несколько каскадных путей от Master к SomeOtherTable (один через Detail1 и один через Detail2). Возможно, вы уже поняли это. Вот возможное решение:

Master { ID, masterfields }

DetailMain { ID, MasterID }

Detail1 { DetailMainID, detail1fields }

Detail2 { DetailMainID, detail2fields }

SomeOtherTable {ID, DetailMainID, someothertablefields }

Все поля ID являются ключевыми полями и автоинкрементными. Суть заключается в полях DetailMainId таблиц Detail. Эти поля являются одновременно ключевыми и ссылочными. Теперь можно каскадно удалить все, удаляя только основные записи. Недостатком является то, что для каждой detail1-записи и для каждой detail2-записи должна существовать DetailMain-запись (которая фактически создается первой, чтобы получить правильный и уникальный идентификатор).

89
ответ дан 23 November 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: